package com.interview.books.topcoder.geometry; import com.interview.leetcode.utils.Point; import java.util.Arrays; import java.util.Comparator; import java.util.SortedSet; import java.util.TreeSet; /** * Created_By: stefanie * Date: 15-1-12 * Time: 上午11:28 */ public class TC_G14_ClosestPair { static Comparator<Point> HORIZONTAL_COMPARATOR = new Comparator<Point>() { @Override public int compare(Point o1, Point o2) { if(o1.x == o2.x) return o1.y - o2.y; else return o1.x - o2.x; } }; static Comparator<Point> VERTICAL_COMPARATOR = new Comparator<Point>() { @Override public int compare(Point o1, Point o2) { if(o1.y == o2.y) return o1.x - o2.x; else return o1.y - o2.y; } }; public Point[] closest(Point[] points){ Point[] closestPair = new Point[2]; double minDistance = 1000.0; Arrays.sort(points, HORIZONTAL_COMPARATOR); //When we start the left most candidate is the first one int mostLeft = 0; //Vertically sorted set of candidates SortedSet<Point> candidates = new TreeSet(VERTICAL_COMPARATOR); //For each point from left to right for (Point current : points){ //Shrink the candidates based on X axis distance while (current.x - points[mostLeft].x > minDistance) { candidates.remove(points[mostLeft]); mostLeft++; } //Shrink the searching area as the rectangle by Y axis distance Point upper = new Point(current.x, (int) (Math.ceil(current.y - minDistance))); Point lower = new Point(current.x, (int) (Math.floor(current.y + minDistance))); //We take only the interesting candidates in the y axis for (Point point : candidates.subSet(upper, lower)) { double distance = distance(current, point); //Simple min computation if (distance < minDistance) { minDistance = distance; closestPair[0] = current; closestPair[1] = point; } } //The current point is now a candidate candidates.add(current); } return closestPair; } public double distance(Point p1, Point p2){ int x = p1.x - p2.x; int y = p1.y - p2.y; return Math.sqrt(x * x + y * y); } public static void main(String[] args){ TC_G14_ClosestPair finder = new TC_G14_ClosestPair(); Point[] points = new Point[6]; points[0] = new Point(1,2); points[1] = new Point(3,1); points[2] = new Point(4,2); points[3] = new Point(5,2); points[4] = new Point(6,4); points[5] = new Point(7,3); Point[] closest = finder.closest(points); System.out.println(closest[0].x + ", " + closest[0].y); //4,2 System.out.println(closest[1].x + ", " + closest[1].y); //5,2 } }