Lintcode-K个最近的点(#612)
描述:
给定一些 points 和一个 origin,从 points 中找到 k 个离 origin 最近的点。按照距离由小到大返回。如果两个点有相同距离,则按照x值来排序;若x值也相同,就再按照y值排序。
样例
给出 points = [[4,6],[4,7],[4,4],[2,5],[1,1]], origin = [0, 0], k = 3
返回 [[1,1],[2,5],[4,4]]
思路:
这一题主要是对Comparator的考察。我们根据题目给出的Point数组 points[]以及Point对象 origin来计算相邻两个points对象与origin的距离(这里根据两点之间距离公式计算,因为求平方根有时候不会得到整数,所以不求平方根),当距离相同的时候,首先根据成员变量x排序;若距离和成员变量x也相同,再根据成员变量y排序。
注意:因为我们写的匿名内部类Comparator,如果我们要在匿名内部类中使用局部变量,那么局部变量必须使用final修饰符来修饰。这是因为内部类可能会扩大局部变量的作用域,对于局部变量而言,方法执行结束局部变量应该随之消失;当内部类则可能产生隐式的”闭包(Closure)”,闭包将使得局部变量脱离它所在的方法继续存在,那会引起极大的混乱。
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
/*
Definition for a point.
*/
class Point {
int x;
int y;
Point() { x = 0; y = 0; }
Point(int a, int b) { x = a; y = b; }
}
public class KClosest612 {//这题的核心就是写Comparator,务必要会写匿名内部类的Comparator
public Point[] kClosest(Point[] points, Point origin, int k) {
// Write your code here
final int originx = origin.x;
final int originy = origin.y;
Arrays.sort(points, new Comparator<Point>(){
@Override
public int compare(Point o1, Point o2) {
// TODO Auto-generated method stub
int firstdis = (int) ((Math.abs(o1.x - originx) * Math.abs(o1.x - originx))+(Math.abs(o1.y - originy) * Math.abs(o1.y - originy)));
int seconddis = (int) ((Math.abs(o2.x - originx) * Math.abs(o2.x - originx))+(Math.abs(o2.y - originy) * Math.abs(o2.y - originy)));
int disdiff = firstdis - seconddis;
if(disdiff < 0){
return -1;
}
else if(disdiff > 0){
return 1;
}
else{
if(o1.x < o2.x){
return -1;
}
else if(o1.x > o2.x){
return 1;
}
else{
if(o1.y < o2.y){
return -1;
}
else if(o1.y > o2.y){
return 1;
}
else{
return 0;
}
}
}
}
});
Point[] tmp = new Point[k];
for(int i = 0; i < k; i++){
tmp[i] = points[i];
}
return tmp;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
KClosest612 sl = new KClosest612();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Point[] points = new Point[n];
for(int i = 0; i < n; i++){
int a = sc.nextInt();
int b = sc.nextInt();
points[i] = new Point(a,b);
}
int a = sc.nextInt();
int b = sc.nextInt();
Point origin = new Point(a,b);
int k = sc.nextInt();
sc.close();
Point[] tmp = sl.kClosest(points, origin, k);
for(int i = 0; i < k; i++){
System.out.println(tmp[i].x + " " + tmp[i].y);
}
}
}