美文网首页
LintCode 612. K个最近的点

LintCode 612. K个最近的点

作者: Jay_8d33 | 来源:发表于2018-02-03 00:46 被阅读0次

原题

第一步,万年不变的查错。如果给的array是null或空,直接return 0

    public Point[] kClosest(Point[] points, Point origin, int k) {
        Point[] result = new Point[k];
        if (points == null || points.length == 0) {
            return result;
        }
        ...
    }

只要见到要找k个最x的,我觉得基本上就是PriorityQueue了。这个题也不例外。根据题意,需要自己写一个comparator。因为是找k个最近的,也就是最小的,所以需要MaxHeap。因为最大的那个就是第k个最小的。所有比它大的都肯定不是前k个最小的。而有小的加进来之后,总共就有k+1个了,那么就要poll掉当前最大的一个。所以MaxHeap在这种情况下是最好的。而降序的comparator实际上就是反过来比(只需要记得默认是升序的就行,反过来的升序,就是降序了)。

        Queue<Point> distance = new PriorityQueue<>((a, b) -> {
            int diff = Double.compare(getDistance(b, origin), getDistance(a, origin));
            if (diff == 0) {
                diff = b.x - a.x;
            }
            if (diff == 0) {
                diff = b.y - a.y;
            }
            
            return diff;
        });

这里用到了getDistance来计算两点之间的距离。公式记不住也不要紧吧,毕竟面试不是考数学的,问一下就行。这里有一个小优化我没有做。因为所有坐标都是正数,所以两点之间的距离必定大于一,在我们不需要知道具体的距离,只需要知道谁大谁小的时候,不需要开平方根了,因为given a > 1 and b > 1, if a > b then a^2 > b^2。不过这个优化太小,如果面试时直接给出这样的优化,面试官肯定瞬间明白你做过这道题。这种小优化不如留到最后,都做完了,再看一遍,再说也不迟。不优化是正常思路。

    private double getDistance(Point a, Point b) {
        return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }

然后就是把array里面的点放到PriorityQueue里面了。这个地方其实可以peek一下做对比,如果大于peek的点,就不add。不过这样的话,comparator的逻辑就要写到外面,或者存下来。直接加进去,然后看有没有超过k个,超过了就poll掉最大的,也可以。不算最优,但好在简练。

        for (Point point : points) {
            distance.add(point);
            if (distance.size() > k) {
                distance.poll();
            }
        }

最后,因为是MaxHeap,里面出来的是降序的,题目要求返回升序的,所以倒着存放poll出来的点就可以了。

        for (int i = k - 1; i >= 0; i--) {
            result[i] = distance.poll();
        }
        
        return result;

完整的code

/**
 * 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 Solution {
    /*
     * @param points: a list of points
     * @param origin: a point
     * @param k: An integer
     * @return: the k closest points
     */
    public Point[] kClosest(Point[] points, Point origin, int k) {
        Point[] result = new Point[k];
        if (points == null || points.length == 0) {
            return result;
        }
        Queue<Point> distance = new PriorityQueue<>((a, b) -> {
            int diff = Double.compare(getDistance(b, origin), getDistance(a, origin));
            if (diff == 0) {
                diff = b.x - a.x;
            }
            if (diff == 0) {
                diff = b.y - a.y;
            }
            
            return diff;
        });
        
        for (Point point : points) {
            distance.add(point);
            if (distance.size() > k) {
                distance.poll();
            }
        }
        
        for (int i = k - 1; i >= 0; i--) {
            result[i] = distance.poll();
        }
        
        return result;
        
    }
    
    private double getDistance(Point a, Point b) {
        return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
}

分析

时间复杂度

生成size为k的PriorityQueue,是O(k)。然后k后面每个数,insert要log(k),所以是O((n - k) * logk)。最后取出来是O(klogk)。所以答案是O(k + (n-k)*logk+klogk) = O(k + nlogk) = O(nlogk)。

空间复杂度

用了一个size为k的queue,所以是O(k)。

感觉这道题最难的地方是分析时间复杂度了吧。解题真的不难,逻辑很简单,只要会用PriorityQueue就可以了。

相关文章

  • LintCode 612. K个最近的点

    原题 解 第一步,万年不变的查错。如果给的array是null或空,直接return 0 只要见到要找k个最x的,...

  • LintCode 612. K个最近的点

    题目描述 给定一些points和一个origin,从points中找到k个离origin最近的点。按照距离由小到大...

  • LintCode K个最近的点

    问题 给定一些 points 和一个 origin,从 points 中找到 k 个离 origin 最近的点。按...

  • 612. K Closest Points

    Description Given some points and an origin point in two-...

  • 612. K Closest Points

    Description Given somepointsand anoriginpoint in two-dime...

  • Remove K Digits

    https://www.lintcode.com/problem/remove-k-digits/description

  • LintCode 5. Kth Largest Element

    原题 LintCode 5. Kth Largest Element Description Find K-th ...

  • 第k大元素

    (lintcode上面的题解)第k大元素:(从小到大的排序)

  • kNN算法/K近邻算法

    深度学习:KNN算法/k近邻算法 算法介绍   即在一个数据集当中寻找其最近的K个点(欧拉距离),由这最近的K个点...

  • LintCode 合并k个排序链表

    题目 合并k个排序链表,并且返回合并后的排序链表。尝试分析和描述其复杂度。 样例给出3个排序链表[2->4->nu...

网友评论

      本文标题:LintCode 612. K个最近的点

      本文链接:https://www.haomeiwen.com/subject/tqrynxtx.html