LeetCode 973. K Closest Points to Origin
      
        Problem LeetCode 973. K Closest Points to Origin 
1. 题目简述 给出某二维平面上的一些坐标,例如[1, 2],找出这些坐标中距离原点最近的K个节点。例如:
Input: points = [[1,3],[-2,2]], K = 1
Output: [[-2,2]]
 
Note:
1 <= K <= points.length <= 10000
-10000 < points[i][0] < 10000
-10000 < points[i][1] < 10000
 
2. 算法思路 这道题难倒是不难,思路也很明确,其实主要是考察数据结构的熟悉程度以及API的调用,否则写起来很麻烦。
暴力解法 首先我们需要记录每个节点与原点的距离,然后进行排序,找出前k个,并把这k个的对应的pair找出来。
用最笨的办法的话就是用个map记录一下distance和对应的index之间的关系,然后排序结束以后找出前k的distance,然后再从map中找出index,再进行遍历。这个方法很麻烦,而且耗时长。
使用Arrays.sort方法自定义排序 我们知道Arrays.sort函数可以默认排序数字类型,但是其更广泛的用法其实是自定义排序任意类型,这点和Collections.sort一个道理。
详情见:Java知识点记录——第一项 
使用PriorityQueue自定义比较方式 同上,只不过queue也是一种List,可以用Comparator来自定义比较方式从而初始化一个小顶堆。这里有两种方式,多种写法。
分治法 找top k问题的常见套路,写一个helper函数来找一个合适的mid,其实并不需要全局有序,只要部分有序就可以了。
3. 解法 暴力解法代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class  Solution   {    public  int [][] kClosest(int [][] points, int  K) {         Map<Integer, List<Integer>> distanceMap = new  HashMap();         List<Integer> distances = new  ArrayList();         for  (int  i = 0 ; i < points.length; i++) {             int  distance = points[i][0 ] * points[i][0 ] + points[i][1 ] * points[i][1 ];             distances.add(distance);             if  (!distanceMap.containsKey(distance)) {                 distanceMap.put(distance, new  ArrayList<Integer>());             }             distanceMap.get(distance).add(i);         }         Collections.sort(distances);         int [][] res = new  int [K][2 ];         int  count = 0 , index = 0 ;         while  (count < K) {             int  target = distances.get(index);             List<Integer> targetIndexes = distanceMap.get(target);             for  (int  i = 0 ; i < targetIndexes.size(); i++) {                 int  x = targetIndexes.get(i);                 res[count][0 ] = points[x][0 ];                 res[count][1 ] = points[x][1 ];                 count++;             }             index++;         }         return  res;     } } 
 
使用Arrays.sort() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class  Solution   {         public  int [][] kClosest(int [][] points, int  K) {         int [][] res = new  int [K][2 ];         int  index = 0 ;         Arrays.sort(points, (point1, point2) -> point1[0 ] * point1[0 ] + point1[1 ] * point1[1 ] - point2[0 ] * point2[0 ] - point2[1 ] * point2[1 ]);         while  (index < K) {             res[index] = points[index];             index++;         }         return  res;     }          public  int [][] kClosest(int [][] points, int  K) {         Arrays.sort(points, Comparator.comparing(p -> p[0 ] * p[0 ] + p[1 ] * p[1 ]));         return  Arrays.copyOfRange(points, 0 , K);     } } 
 
使用PriorityQueu+Comparator 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class  Solution   {    public  int [][] kClosest(int [][] points, int  K) {                  PriorityQueue<int []> queue = new  PriorityQueue<int []>((p1, p2) -> p2[0 ] * p2[0 ] + p2[1 ] * p2[1 ] - p1[0 ] * p1[0 ] - p1[1 ] * p1[1 ]);         for  (int [] p : points) {             queue.offer(p);             if  (queue.size() > K) {                 queue.poll();             }         }         int [][] res = new  int [K][2 ];         while  (K > 0 ) {             res[--K] = queue.poll();         }         return  res;     }     public  int [][] kClosest(int [][] points, int  K) {                  PriorityQueue<int []> queue = new  PriorityQueue<int []>((p1, p2) -> p1[0 ] * p1[0 ] + p1[1 ] * p1[1 ] - p2[0 ] * p2[0 ] - p2[1 ] * p2[1 ]);         queue.addAll(Arrays.asList(points));         int [][] res = new  int [K][2 ];         while  (K > 0 ) {             res[--K] = queue.poll();         }         return  res;     } } 
 
使用分治法找top k 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class  Solution   {    public  int [][] kClosest(int [][] points, int  K) {         int  l = 0 , r = points.length - 1 ,         while  (l <= r) {             int  mid = helper(points, l, r);             if  (mid == K) {                 break ;             } else  if  (mid < K) {                 l = mid + 1 ;             } else  if  (mid > K) {                 r = mid - 1 ;             }         }         return  Arrays.copyOfRange(points, 0 , K);     }     private  int  helper (int [][] points, int  l, int  r)   {         int [] pivot = points[l];         while  (l < r) {             while  (l < r && compare(points[r], pivot)) {                 r--;             }             points[l] = points[r];             while  (l < r && compare(pivot, points[l])) {                 l++;             }             points[r] = points[l];         }         points[l] = pivot;         return  l;     }          private  boolean  compare (int [] p1, int [] p2)   {         return  (p1[0 ] * p1[0 ] + p1[1 ] * p1[1 ] - p2[0 ] * p2[0 ] - p2[1 ] * p2[1 ]) >= 0 ;     } }