Skip to content

Commit 9a5e40e

Browse files
committed
updated closest pair of points (n*(logn)^2) to (n*logn)
1 parent 990375d commit 9a5e40e

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

divide_and_conquer/closest_pair_of_points.py

+21-16
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
"""
22
The algorithm finds distance btw closest pair of points in the given n points.
33
Approach used -> Divide and conquer
4-
The points are sorted based on Xco-ords
4+
The points are sorted based on Xco-ords and
5+
then based on Yco-ords separetely.
56
& by applying divide and conquer approach,
67
minimum distance is obtained recursively.
78
89
>> closest points lie on different sides of partition
910
This case handled by forming a strip of points
1011
whose Xco-ords distance is less than closest_pair_dis
11-
from mid-point's Xco-ords.
12+
from mid-point's Xco-ords. points sorted based on Yco-ords
13+
are used in this step to reduce sorting time.
1214
Closest pair distance is found in the strip of points. (closest_in_strip)
1315
1416
min(closest_pair_dis, closest_in_strip) would be the final answer.
1517
16-
Time complexity: O(n * (logn)^2)
18+
Time complexity: O(n * logn)
1719
"""
1820

1921

20-
import math
21-
22-
2322
def euclidean_distance_sqr(point1, point2):
2423
return pow(point1[0] - point2[0], 2) + pow(point1[1] - point2[1], 2)
2524

@@ -66,7 +65,7 @@ def dis_between_closest_in_strip(points, points_counts, min_dis = float("inf")):
6665
return min_dis
6766

6867

69-
def closest_pair_of_points_sqr(points, points_counts):
68+
def closest_pair_of_points_sqr(points_sorted_on_X, points_sorted_on_Y, points_counts):
7069
""" divide and conquer approach
7170
7271
Parameters :
@@ -79,35 +78,41 @@ def closest_pair_of_points_sqr(points, points_counts):
7978

8079
# base case
8180
if points_counts <= 3:
82-
return dis_between_closest_pair(points, points_counts)
81+
return dis_between_closest_pair(points_sorted_on_X, points_counts)
8382

8483
# recursion
8584
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)
85+
closest_in_left = closest_pair_of_points_sqr(points_sorted_on_X,
86+
points_sorted_on_Y[:mid],
87+
mid)
88+
closest_in_right = closest_pair_of_points_sqr(points_sorted_on_Y,
89+
points_sorted_on_Y[mid:],
90+
points_counts - mid)
8891
closest_pair_dis = min(closest_in_left, closest_in_right)
8992

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

9497
cross_strip = []
95-
for point in points:
96-
if abs(point[0] - points[mid][0]) < closest_pair_dis:
98+
for point in points_sorted_on_X:
99+
if abs(point[0] - points_sorted_on_X[mid][0]) < closest_pair_dis:
97100
cross_strip.append(point)
98101

99-
cross_strip = column_based_sort(cross_strip, 1)
100102
closest_in_strip = dis_between_closest_in_strip(cross_strip,
101103
len(cross_strip), closest_pair_dis)
102104
return min(closest_pair_dis, closest_in_strip)
103105

104106

105107
def closest_pair_of_points(points, points_counts):
106-
return math.sqrt(closest_pair_of_points_sqr(points, points_counts))
108+
points_sorted_on_X = column_based_sort(points, column = 0)
109+
points_sorted_on_Y = column_based_sort(points, column = 1)
110+
return (closest_pair_of_points_sqr(points_sorted_on_X,
111+
points_sorted_on_Y,
112+
points_counts)) ** 0.5
107113

108114

109-
points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (0, 2), (5, 6), (1, 2)]
110-
points = column_based_sort(points)
115+
points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
111116
print("Distance:", closest_pair_of_points(points, len(points)))
112117

113118

0 commit comments

Comments
 (0)