Skip to content

Commit f111af6

Browse files
Added RandomizedClosestPair code and test
1 parent ad5e496 commit f111af6

2 files changed

Lines changed: 153 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package com.thealgorithms.randomized;
2+
3+
import java.util.Arrays;
4+
import java.util.Collections;
5+
import java.util.Comparator;
6+
import java.util.List;
7+
import java.util.ArrayList;
8+
import java.util.Random;
9+
10+
/**
11+
* Randomized Closest Pair of Points Algorithm
12+
*
13+
* Use Case:
14+
* - Efficiently finds the closest pair of points in a 2D plane.
15+
* - Applicable in computational geometry, clustering, and graphics.
16+
*
17+
* Time Complexity:
18+
* - Expected: O(n log n) using randomized divide and conquer
19+
*
20+
* @see <a href="https://en.wikipedia.org/wiki/Closest_pair_of_points_problem">Closest Pair of Points - Wikipedia</a>
21+
*/
22+
public final class RandomizedClosestPair {
23+
24+
// Prevent instantiation of utility class
25+
private RandomizedClosestPair() {
26+
throw new UnsupportedOperationException("Utility class");
27+
}
28+
29+
public static class Point {
30+
public final double x, y;
31+
public Point(double x, double y) {
32+
this.x = x;
33+
this.y = y;
34+
}
35+
}
36+
37+
public static double findClosestPairDistance(Point[] points) {
38+
List<Point> shuffled = new ArrayList<>(Arrays.asList(points));
39+
Collections.shuffle(shuffled, new Random());
40+
41+
Point[] px = shuffled.toArray(new Point[0]);
42+
Arrays.sort(px, Comparator.comparingDouble(p -> p.x));
43+
44+
Point[] py = px.clone();
45+
Arrays.sort(py, Comparator.comparingDouble(p -> p.y));
46+
47+
return closestPair(px, py);
48+
}
49+
50+
private static double closestPair(Point[] px, Point[] py) {
51+
int n = px.length;
52+
if (n <= 3) {
53+
return bruteForce(px);
54+
}
55+
56+
int mid = n / 2;
57+
Point midPoint = px[mid];
58+
59+
Point[] Qx = Arrays.copyOfRange(px, 0, mid);
60+
Point[] Rx = Arrays.copyOfRange(px, mid, n);
61+
62+
List<Point> Qy = new ArrayList<>();
63+
List<Point> Ry = new ArrayList<>();
64+
for (Point p : py) {
65+
if (p.x <= midPoint.x) Qy.add(p);
66+
else Ry.add(p);
67+
}
68+
69+
double d1 = closestPair(Qx, Qy.toArray(new Point[0]));
70+
double d2 = closestPair(Rx, Ry.toArray(new Point[0]));
71+
72+
double d = Math.min(d1, d2);
73+
74+
List<Point> strip = new ArrayList<>();
75+
for (Point p : py) {
76+
if (Math.abs(p.x - midPoint.x) < d) {
77+
strip.add(p);
78+
}
79+
}
80+
81+
return Math.min(d, stripClosest(strip, d));
82+
}
83+
84+
private static double bruteForce(Point[] points) {
85+
double min = Double.POSITIVE_INFINITY;
86+
for (int i = 0; i < points.length; i++) {
87+
for (int j = i + 1; j < points.length; j++) {
88+
min = Math.min(min, distance(points[i], points[j]));
89+
}
90+
}
91+
return min;
92+
}
93+
94+
private static double stripClosest(List<Point> strip, double d) {
95+
double min = d;
96+
int n = strip.size();
97+
for (int i = 0; i < n; i++) {
98+
for (int j = i + 1; j < n && (strip.get(j).y - strip.get(i).y) < min; j++) {
99+
min = Math.min(min, distance(strip.get(i), strip.get(j)));
100+
}
101+
}
102+
return min;
103+
}
104+
105+
private static double distance(Point p1, Point p2) {
106+
return Math.hypot(p1.x - p2.x, p1.y - p2.y);
107+
}
108+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.thealgorithms.randomized;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import com.thealgorithms.randomized.RandomizedClosestPair.Point;
6+
import org.junit.jupiter.api.Test;
7+
8+
public class RandomizedClosestPairTest {
9+
10+
@Test
11+
public void testClosestPairBasic() {
12+
Point[] points = new Point[] {
13+
new Point(2, 3),
14+
new Point(12, 30),
15+
new Point(40, 50),
16+
new Point(5, 1),
17+
new Point(12, 10),
18+
new Point(3, 4)
19+
};
20+
double result = RandomizedClosestPair.findClosestPairDistance(points);
21+
assertEquals(Math.hypot(1, 1), result, 0.01); // Closest pair: (2,3) and (3,4)
22+
}
23+
24+
@Test
25+
public void testIdenticalPoints() {
26+
Point[] points = new Point[] {
27+
new Point(0, 0),
28+
new Point(0, 0),
29+
new Point(1, 1),
30+
};
31+
double result = RandomizedClosestPair.findClosestPairDistance(points);
32+
assertEquals(0.0, result, 0.00001);
33+
}
34+
35+
@Test
36+
public void testMinimalCase() {
37+
Point[] points = new Point[] {
38+
new Point(0, 0),
39+
new Point(3, 4)
40+
};
41+
double result = RandomizedClosestPair.findClosestPairDistance(points);
42+
assertEquals(5.0, result, 0.00001);
43+
}
44+
}
45+

0 commit comments

Comments
 (0)