Skip to content

Commit

Permalink
closest pair of points algo (TheAlgorithms#943)
Browse files Browse the repository at this point in the history
* created divide_and_conquer folder and added max_sub_array_sum.py under it (issue TheAlgorithms#817)

* additional file in divide_and_conqure (closest pair of points)
  • Loading branch information
Dharni0607 authored and Erfaniaa committed Jul 4, 2019
1 parent 03f9940 commit 035457f
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 0 deletions.
113 changes: 113 additions & 0 deletions divide_and_conquer/closest_pair_of_points.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""
The algorithm finds distance btw closest pair of points in the given n points.
Approach used -> Divide and conquer
The points are sorted based on Xco-ords
& by applying divide and conquer approach,
minimum distance is obtained recursively.
>> closest points lie on different sides of partition
This case handled by forming a strip of points
whose Xco-ords distance is less than closest_pair_dis
from mid-point's Xco-ords.
Closest pair distance is found in the strip of points. (closest_in_strip)
min(closest_pair_dis, closest_in_strip) would be the final answer.
Time complexity: O(n * (logn)^2)
"""


import math


def euclidean_distance_sqr(point1, point2):
return pow(point1[0] - point2[0], 2) + pow(point1[1] - point2[1], 2)


def column_based_sort(array, column = 0):
return sorted(array, key = lambda x: x[column])


def dis_between_closest_pair(points, points_counts, min_dis = float("inf")):
""" brute force approach to find distance between closest pair points
Parameters :
points, points_count, min_dis (list(tuple(int, int)), int, int)
Returns :
min_dis (float): distance between closest pair of points
"""

for i in range(points_counts - 1):
for j in range(i+1, points_counts):
current_dis = euclidean_distance_sqr(points[i], points[j])
if current_dis < min_dis:
min_dis = current_dis
return min_dis


def dis_between_closest_in_strip(points, points_counts, min_dis = float("inf")):
""" closest pair of points in strip
Parameters :
points, points_count, min_dis (list(tuple(int, int)), int, int)
Returns :
min_dis (float): distance btw closest pair of points in the strip (< min_dis)
"""

for i in range(min(6, points_counts - 1), points_counts):
for j in range(max(0, i-6), i):
current_dis = euclidean_distance_sqr(points[i], points[j])
if current_dis < min_dis:
min_dis = current_dis
return min_dis


def closest_pair_of_points_sqr(points, points_counts):
""" divide and conquer approach
Parameters :
points, points_count (list(tuple(int, int)), int)
Returns :
(float): distance btw closest pair of points
"""

# base case
if points_counts <= 3:
return dis_between_closest_pair(points, points_counts)

# recursion
mid = points_counts//2
closest_in_left = closest_pair_of_points(points[:mid], mid)
closest_in_right = closest_pair_of_points(points[mid:], points_counts - mid)
closest_pair_dis = min(closest_in_left, closest_in_right)

""" cross_strip contains the points, whose Xcoords are at a
distance(< closest_pair_dis) from mid's Xcoord
"""

cross_strip = []
for point in points:
if abs(point[0] - points[mid][0]) < closest_pair_dis:
cross_strip.append(point)

cross_strip = column_based_sort(cross_strip, 1)
closest_in_strip = dis_between_closest_in_strip(cross_strip,
len(cross_strip), closest_pair_dis)
return min(closest_pair_dis, closest_in_strip)


def closest_pair_of_points(points, points_counts):
return math.sqrt(closest_pair_of_points_sqr(points, points_counts))


points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (0, 2), (5, 6), (1, 2)]
points = column_based_sort(points)
print("Distance:", closest_pair_of_points(points, len(points)))


75 changes: 75 additions & 0 deletions divide_and_conquer/max_subarray_sum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""
Given a array of length n, max_subarray_sum() finds
the maximum of sum of contiguous sub-array using divide and conquer method.
Time complexity : O(n log n)
Ref : INTRODUCTION TO ALGORITHMS THIRD EDITION
(section : 4, sub-section : 4.1, page : 70)
"""


def max_sum_from_start(array):
""" This function finds the maximum contiguous sum of array from 0 index
Parameters :
array (list[int]) : given array
Returns :
max_sum (int) : maximum contiguous sum of array from 0 index
"""
array_sum = 0
max_sum = float("-inf")
for num in array:
array_sum += num
if array_sum > max_sum:
max_sum = array_sum
return max_sum


def max_cross_array_sum(array, left, mid, right):
""" This function finds the maximum contiguous sum of left and right arrays
Parameters :
array, left, mid, right (list[int], int, int, int)
Returns :
(int) : maximum of sum of contiguous sum of left and right arrays
"""

max_sum_of_left = max_sum_from_start(array[left:mid+1][::-1])
max_sum_of_right = max_sum_from_start(array[mid+1: right+1])
return max_sum_of_left + max_sum_of_right


def max_subarray_sum(array, left, right):
""" Maximum contiguous sub-array sum, using divide and conquer method
Parameters :
array, left, right (list[int], int, int) :
given array, current left index and current right index
Returns :
int : maximum of sum of contiguous sub-array
"""

# base case: array has only one element
if left == right:
return array[right]

# Recursion
mid = (left + right) // 2
left_half_sum = max_subarray_sum(array, left, mid)
right_half_sum = max_subarray_sum(array, mid + 1, right)
cross_sum = max_cross_array_sum(array, left, mid, right)
return max(left_half_sum, right_half_sum, cross_sum)


array = [-2, -5, 6, -2, -3, 1, 5, -6]
array_length = len(array)
print("Maximum sum of contiguous subarray:", max_subarray_sum(array, 0, array_length - 1))

0 comments on commit 035457f

Please sign in to comment.