import
java.util.Arrays;
import
java.util.List;
import
java.util.ArrayList;
class
Point {
public
int
x;
public
int
y;
public
Point(
int
x,
int
y) {
this
.x = x;
this
.y = y;
}
}
public
class
ClosestPair {
public
static
double
closest(Point[] P,
int
n) {
Point[] Px = Arrays.copyOf(P, n);
Arrays.sort(Px, (p1, p2) -> p1.x - p2.x);
Point[] Py = Arrays.copyOf(P, n);
Arrays.sort(Py, (p1, p2) -> p1.y - p2.y);
return
closestUtil(Px, Py, n);
}
private
static
double
closestUtil(Point[] Px, Point[] Py,
int
n) {
if
(n <=
3
) {
return
bruteForce(Px, n);
}
int
mid = n /
2
;
Point midPoint = Px[mid];
Point[] Pyl = Arrays.copyOfRange(Py,
0
, mid);
Point[] Pyr = Arrays.copyOfRange(Py, mid, n);
double
dl = closestUtil(Px, Pyl, mid);
double
dr = closestUtil(Arrays.copyOfRange(Px, mid, n), Pyr, n - mid);
double
d = Math.min(dl, dr);
List<Point> strip =
new
ArrayList<Point>();
for
(Point p : Py) {
if
(Math.abs(p.x - midPoint.x) < d) {
strip.add(p);
}
}
return
stripClosest(strip.toArray(
new
Point[strip.size()]), strip.size(), d);
}
private
static
double
bruteForce(Point[] P,
int
n) {
double
min = Double.MAX_VALUE;
for
(
int
i =
0
; i < n; ++i) {
for
(
int
j = i +
1
; j < n; ++j) {
double
dist = distance(P[i], P[j]);
if
(dist < min) {
min = dist;
}
}
}
return
min;
}
private
static
double
stripClosest(Point[] strip,
int
size,
double
d) {
double
min = d;
for
(
int
i =
0
; i < size; ++i) {
for
(
int
j = i +
1
; j < size && (strip[j].y - strip[i].y) < min; ++j) {
double
dist = distance(strip[i], strip[j]);
if
(dist < min) {
min = dist;
}
}
}
return
min;
}
private
static
double
distance(Point p1, Point p2) {
return
Math.sqrt(Math.pow(p1.x - p2.x,
2
) + Math.pow(p1.y - p2.y,
2
));
}
public
static
void
main(String[] args) {
Point[] P = {
new
Point(
2
,
3
),
new
Point(
12
,
30
),
new
Point(
40
,
50
),
new
Point(
5
,
1
),
new
Point(
12
,
10
),
new
Point(
3
,
4
) };
int
n = P.length;
System.out.println(
"The smallest distance is "
+ closest(P, n));
}
}