Skip to content

Commit 85d7665

Browse files
Dharni0607stokhos
authored andcommitted
closest pair of points algo (TheAlgorithms#943)
* 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)
1 parent dda3089 commit 85d7665

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed

Diff for: divide_and_conquer/closest_pair_of_points.py

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""
2+
The algorithm finds distance btw closest pair of points in the given n points.
3+
Approach used -> Divide and conquer
4+
The points are sorted based on Xco-ords
5+
& by applying divide and conquer approach,
6+
minimum distance is obtained recursively.
7+
8+
>> closest points lie on different sides of partition
9+
This case handled by forming a strip of points
10+
whose Xco-ords distance is less than closest_pair_dis
11+
from mid-point's Xco-ords.
12+
Closest pair distance is found in the strip of points. (closest_in_strip)
13+
14+
min(closest_pair_dis, closest_in_strip) would be the final answer.
15+
16+
Time complexity: O(n * (logn)^2)
17+
"""
18+
19+
20+
import math
21+
22+
23+
def euclidean_distance_sqr(point1, point2):
24+
return pow(point1[0] - point2[0], 2) + pow(point1[1] - point2[1], 2)
25+
26+
27+
def column_based_sort(array, column = 0):
28+
return sorted(array, key = lambda x: x[column])
29+
30+
31+
def dis_between_closest_pair(points, points_counts, min_dis = float("inf")):
32+
""" brute force approach to find distance between closest pair points
33+
34+
Parameters :
35+
points, points_count, min_dis (list(tuple(int, int)), int, int)
36+
37+
Returns :
38+
min_dis (float): distance between closest pair of points
39+
40+
"""
41+
42+
for i in range(points_counts - 1):
43+
for j in range(i+1, points_counts):
44+
current_dis = euclidean_distance_sqr(points[i], points[j])
45+
if current_dis < min_dis:
46+
min_dis = current_dis
47+
return min_dis
48+
49+
50+
def dis_between_closest_in_strip(points, points_counts, min_dis = float("inf")):
51+
""" closest pair of points in strip
52+
53+
Parameters :
54+
points, points_count, min_dis (list(tuple(int, int)), int, int)
55+
56+
Returns :
57+
min_dis (float): distance btw closest pair of points in the strip (< min_dis)
58+
59+
"""
60+
61+
for i in range(min(6, points_counts - 1), points_counts):
62+
for j in range(max(0, i-6), i):
63+
current_dis = euclidean_distance_sqr(points[i], points[j])
64+
if current_dis < min_dis:
65+
min_dis = current_dis
66+
return min_dis
67+
68+
69+
def closest_pair_of_points_sqr(points, points_counts):
70+
""" divide and conquer approach
71+
72+
Parameters :
73+
points, points_count (list(tuple(int, int)), int)
74+
75+
Returns :
76+
(float): distance btw closest pair of points
77+
78+
"""
79+
80+
# base case
81+
if points_counts <= 3:
82+
return dis_between_closest_pair(points, points_counts)
83+
84+
# recursion
85+
mid = points_counts//2
86+
closest_in_left = closest_pair_of_points(points[:mid], mid)
87+
closest_in_right = closest_pair_of_points(points[mid:], points_counts - mid)
88+
closest_pair_dis = min(closest_in_left, closest_in_right)
89+
90+
""" cross_strip contains the points, whose Xcoords are at a
91+
distance(< closest_pair_dis) from mid's Xcoord
92+
"""
93+
94+
cross_strip = []
95+
for point in points:
96+
if abs(point[0] - points[mid][0]) < closest_pair_dis:
97+
cross_strip.append(point)
98+
99+
cross_strip = column_based_sort(cross_strip, 1)
100+
closest_in_strip = dis_between_closest_in_strip(cross_strip,
101+
len(cross_strip), closest_pair_dis)
102+
return min(closest_pair_dis, closest_in_strip)
103+
104+
105+
def closest_pair_of_points(points, points_counts):
106+
return math.sqrt(closest_pair_of_points_sqr(points, points_counts))
107+
108+
109+
points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (0, 2), (5, 6), (1, 2)]
110+
points = column_based_sort(points)
111+
print("Distance:", closest_pair_of_points(points, len(points)))
112+
113+

Diff for: divide_and_conquer/max_subarray_sum.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
Given a array of length n, max_subarray_sum() finds
3+
the maximum of sum of contiguous sub-array using divide and conquer method.
4+
5+
Time complexity : O(n log n)
6+
7+
Ref : INTRODUCTION TO ALGORITHMS THIRD EDITION
8+
(section : 4, sub-section : 4.1, page : 70)
9+
10+
"""
11+
12+
13+
def max_sum_from_start(array):
14+
""" This function finds the maximum contiguous sum of array from 0 index
15+
16+
Parameters :
17+
array (list[int]) : given array
18+
19+
Returns :
20+
max_sum (int) : maximum contiguous sum of array from 0 index
21+
22+
"""
23+
array_sum = 0
24+
max_sum = float("-inf")
25+
for num in array:
26+
array_sum += num
27+
if array_sum > max_sum:
28+
max_sum = array_sum
29+
return max_sum
30+
31+
32+
def max_cross_array_sum(array, left, mid, right):
33+
""" This function finds the maximum contiguous sum of left and right arrays
34+
35+
Parameters :
36+
array, left, mid, right (list[int], int, int, int)
37+
38+
Returns :
39+
(int) : maximum of sum of contiguous sum of left and right arrays
40+
41+
"""
42+
43+
max_sum_of_left = max_sum_from_start(array[left:mid+1][::-1])
44+
max_sum_of_right = max_sum_from_start(array[mid+1: right+1])
45+
return max_sum_of_left + max_sum_of_right
46+
47+
48+
def max_subarray_sum(array, left, right):
49+
""" Maximum contiguous sub-array sum, using divide and conquer method
50+
51+
Parameters :
52+
array, left, right (list[int], int, int) :
53+
given array, current left index and current right index
54+
55+
Returns :
56+
int : maximum of sum of contiguous sub-array
57+
58+
"""
59+
60+
# base case: array has only one element
61+
if left == right:
62+
return array[right]
63+
64+
# Recursion
65+
mid = (left + right) // 2
66+
left_half_sum = max_subarray_sum(array, left, mid)
67+
right_half_sum = max_subarray_sum(array, mid + 1, right)
68+
cross_sum = max_cross_array_sum(array, left, mid, right)
69+
return max(left_half_sum, right_half_sum, cross_sum)
70+
71+
72+
array = [-2, -5, 6, -2, -3, 1, 5, -6]
73+
array_length = len(array)
74+
print("Maximum sum of contiguous subarray:", max_subarray_sum(array, 0, array_length - 1))
75+

0 commit comments

Comments
 (0)