|
| 1 | +""" |
| 2 | +The algorithm finds distance between closest pair of points in the given n points. |
| 3 | +Approach: Divide and conquer |
| 4 | +The points are sorted based on x-cords |
| 5 | +& by applying divide and conquer approach, |
| 6 | +minimum distance is obtained recursively. |
| 7 | +
|
| 8 | +Edge case: closest points lie on different sides of partition |
| 9 | +This case handled by forming a strip of points |
| 10 | +which are at a distance (< closest_pair_dis) from mid-point. |
| 11 | +(It is a proven that strip contains at most 6 points) |
| 12 | +And brute force method is applied on strip to find closest points. |
| 13 | +
|
| 14 | +Time complexity: O(n * (logn) ^ 2) |
| 15 | +""" |
| 16 | + |
| 17 | + |
| 18 | +import math |
| 19 | + |
| 20 | + |
| 21 | +def euclidean_distance(point1, point2): |
| 22 | + return math.sqrt(pow(point1[0] - point2[0], 2) + pow(point1[1] - point2[1], 2)) |
| 23 | + |
| 24 | + |
| 25 | +def column_based_sort(array, column = 0): |
| 26 | + return sorted(array, key = lambda x: x[column]) |
| 27 | + |
| 28 | + |
| 29 | +#brute force approach to find distance between closest pair points |
| 30 | +def dis_btw_closest_pair(points, no_of_points, min_dis = float("inf")): |
| 31 | + for i in range(no_of_points - 1): |
| 32 | + for j in range(i+1, no_of_points): |
| 33 | + current_dis = euclidean_distance(points[i], points[j]) |
| 34 | + if current_dis < min_dis: |
| 35 | + min_dis = current_dis |
| 36 | + return min_dis |
| 37 | + |
| 38 | + |
| 39 | +#divide and conquer approach |
| 40 | +def closest_pair_of_points(points, no_of_points): |
| 41 | + # base case |
| 42 | + if no_of_points <= 3: |
| 43 | + return dis_btw_closest_pair(points, no_of_points) |
| 44 | + |
| 45 | + #recursion |
| 46 | + mid = no_of_points//2 |
| 47 | + closest_in_left = closest_pair_of_points(points[:mid], mid) |
| 48 | + closest_in_right = closest_pair_of_points(points[mid:], no_of_points - mid) |
| 49 | + closest_pair_dis = min(closest_in_left, closest_in_right) |
| 50 | + |
| 51 | + #points which are at a distance (< closest_pair_dis) from mid-point |
| 52 | + cross_strip = [] |
| 53 | + for point in points: |
| 54 | + if abs(point[0] - points[mid][0]) < closest_pair_dis: |
| 55 | + cross_strip.append(point) |
| 56 | + |
| 57 | + cross_strip = column_based_sort(cross_strip, 1) |
| 58 | + closest_in_strip = dis_btw_closest_pair(cross_strip, |
| 59 | + len(cross_strip), closest_pair_dis) |
| 60 | + return min(closest_pair_dis, closest_in_strip) |
| 61 | + |
| 62 | + |
| 63 | +points = [[2, 3], [12, 30], [40, 50], [5, 1], [12, 10]] |
| 64 | +points = column_based_sort(points) |
| 65 | +print("Distance:", closest_pair_of_points(points, len(points))) |
| 66 | + |
| 67 | + |
0 commit comments