Created
January 7, 2017 16:19
-
-
Save devteampentagon/c529ebb3c268c19fb84dcbe78f0c50e5 to your computer and use it in GitHub Desktop.
Closest Pair Of Points
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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