Skip to content

Commit b75292c

Browse files
committed
closest pair program
1 parent 2320b46 commit b75292c

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.thealgorithms.randomized;
2+
import java.util.*;
3+
import java.math.BigDecimal;
4+
import java.math.RoundingMode;
5+
/**
6+
* This class implements the randomized Closest Pair Algorithm; given some number of points
7+
* in a plane find the pair with minimum euclidean distance from each other. This solution
8+
* uses the divide and conquer approach.
9+
* @author Bri Harris
10+
*/
11+
12+
import java.util.*;
13+
14+
class Point implements Comparable<Point> {
15+
double x, y;
16+
17+
// Constructor to initialize a point with x and y coordinates
18+
Point(double x, double y) {
19+
this.x = x;
20+
this.y = y;
21+
}
22+
23+
// Compare points based on x-coordinates (for sorting)
24+
public int compareTo(Point other) {
25+
return Double.compare(this.x, other.x);
26+
}
27+
28+
// Compute Euclidean distance between two points
29+
static double distance(Point p1, Point p2) {
30+
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
31+
}
32+
}
33+
34+
public class ClosestPair {
35+
public static double closest(List<Point> points) {
36+
Collections.sort(points);
37+
double result = closestRecursiveHelper(points, 0, points.size() - 1);
38+
39+
//Return distance of closest pair rounded to 2 decimal places
40+
return new BigDecimal(result).setScale(2, RoundingMode.HALF_UP).doubleValue();
41+
}
42+
43+
private static double closestRecursiveHelper(List<Point> points, int left, int right) {
44+
//Base Case occurs with 3 or fewer points
45+
if (right - left <= 2) return baseCase(points, left, right);
46+
47+
48+
//Divide and conquer
49+
int mid = (left + right) / 2;
50+
double midX = points.get(mid).x;
51+
52+
double leftDist = closestRecursiveHelper(points, left, mid);
53+
double rightDist = closestRecursiveHelper(points, mid + 1, right);
54+
55+
double minDist = Math.min(leftDist, rightDist);
56+
57+
return checkBoundary(points, left, right, midX, minDist);
58+
}
59+
60+
private static double baseCase(List<Point> points, int left, int right) {
61+
// Sub-problems fitting the base case can use brute force
62+
double minDist = Double.MAX_VALUE;
63+
for (int i = left; i <= right; i++) {
64+
for (int j = i + 1; j <= right; j++) {
65+
minDist = Math.min(minDist, Point.distance(points.get(i), points.get(j)));
66+
}
67+
}
68+
return minDist;
69+
}
70+
71+
private static double checkBoundary(List<Point> points, int left, int right, double midX, double minDist) {
72+
//Consider a boundary by the dividing line
73+
List<Point> boundary = new ArrayList<>();
74+
for (int i = left; i <= right; i++) {
75+
if (Math.abs(points.get(i).x - midX) < minDist) boundary.add(points.get(i));
76+
}
77+
78+
//sort by y coordinate within the boundary and check for closer points
79+
boundary.sort(Comparator.comparingDouble(p -> p.y));
80+
for (int i = 0; i < boundary.size(); i++) {
81+
for (int j = i + 1; j < boundary.size() && (boundary.get(j).y - boundary.get(i).y) < minDist; j++) {
82+
minDist = Math.min(minDist, Point.distance(boundary.get(i), boundary.get(j)));
83+
}
84+
}
85+
return minDist;
86+
}
87+
}

0 commit comments

Comments
 (0)