Skip to content

Instantly share code, notes, and snippets.

@devteampentagon
Created January 7, 2017 16:19
Show Gist options
  • Save devteampentagon/c529ebb3c268c19fb84dcbe78f0c50e5 to your computer and use it in GitHub Desktop.
Save devteampentagon/c529ebb3c268c19fb84dcbe78f0c50e5 to your computer and use it in GitHub Desktop.
Closest Pair Of Points
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* http://www.geeksforgeeks.org/closest-pair-of-points-onlogn-implementation/
* https://www.youtube.com/watch?v=_pSl90jq-m0 another good explanation
* Given coordinates of points find closest pair points distance.
*
* Test cases:
* Number of points should be more than 1
* Test along positive and negative axis
*
* The way it works is
* 1) Sort by x coordinate
* 2) Recursively divide into two halves.
* 3) Find min distance between points in each half. Say this distance is d.
* 4) Find points which are in either half and closer than d. To find this point sort by y
* axis and find distance to next 6 points. Magic about 6 points is we can create a rectangular
* area and only 6 points can fit in that rectangular area. So we need to check only 7 points
* for each point in rectangular area.
* @author tusroy
*/
class Point{
int x;
int y;
Point(int x, int y){
this.x = x;
this.y = y;
}
}
class XCoordinatorSorter implements Comparator<Point>{
@Override
public int compare(Point o1, Point o2) {
if(o1.x < o2.x){
return -1;
}else{
return 1;
}
}
}
class YCoordinatorSorter implements Comparator<Point>{
@Override
public int compare(Point o1, Point o2) {
if(o1.y < o2.y){
return -1;
}else{
return 1;
}
}
}
public class ClosestPairOfPoints {
private static final int SIZE = 7;
public double closestPairOfPoints(Point[] points){
if(points.length < 2){
throw new IllegalArgumentException();
}
Point[] px = new Point[points.length];
Point[] py = new Point[points.length];
int i=0;
for(Point point : points){
px[i++] = point;
}
i=0;
for(Point point : points){
py[i++] = point;
}
XCoordinatorSorter xSorter = new XCoordinatorSorter();
YCoordinatorSorter ySorter = new YCoordinatorSorter();
Arrays.sort(px, xSorter);
Arrays.sort(py, ySorter);
int minDistance = closestPairOfPoints(px, py, 0, points.length-1);
return Math.sqrt(minDistance);
}
private int closestPairOfPoints(Point[] px, Point[] py,int start, int end){
if(end - start < 3){
return computeMinDistance(px, start, end);
}
int mid = (start + end)/2;
Point[] pyLeft = new Point[mid-start+1];
Point[] pyRight = new Point[end-mid];
int i=0, j=0;
for(Point p : px){
if(p.x <= px[mid].x){
pyLeft[i++] = p;
}else{
pyRight[j++] = p;
}
}
int d1 = closestPairOfPoints(px,pyLeft,start,mid);
int d2 = closestPairOfPoints(px, pyRight, mid+1, end);
int d = Math.min(d1, d2);
List<Point> deltaPoints = new ArrayList<Point>();
for(Point p : px){
if(Math.sqrt(distance(p,px[mid])) < Math.sqrt(d)){
deltaPoints.add(p);
}
}
int d3 = closest(deltaPoints);
return Math.min(d3, d);
}
private int closest(List<Point> deltaPoints){
int minDistance = Integer.MAX_VALUE;
for(int i=0; i < deltaPoints.size(); i++){
for(int j=i+1; j <= i + SIZE && j < deltaPoints.size() ; j++){
int distance = distance(deltaPoints.get(i), deltaPoints.get(j));
if(minDistance < distance){
minDistance = distance;
}
}
}
return minDistance;
}
private int distance(Point p1, Point p2){
return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y);
}
private int computeMinDistance(Point[] points, int start, int end){
if(end - start == 1){
Point p1 = points[start];
Point p2 = points[end];
return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y);
}else if(end - start == 2){
Point p1 = points[start];
Point p2 = points[end-1];
Point p3 = points[end];
return Math.min(Math.min((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y),
(p1.x - p3.x)*(p1.x - p3.x) + (p1.y - p3.y)*(p1.y - p3.y)),
(p2.x - p3.x)*(p2.x - p3.x) + (p2.y - p3.y)*(p2.y - p3.y));
}else{
throw new IllegalArgumentException();
}
}
public static void main(String args[]){
ClosestPairOfPoints cpp = new ClosestPairOfPoints();
Point[] points = {new Point(6,2),new Point(4,6),new Point(5,4),new Point(-8,2),new Point(0,2)};
double minDistance = cpp.closestPairOfPoints(points);
System.out.println(minDistance);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment