Lintcode-K个最近的点(#612)

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);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值