[路飞]_每天刷leetcode_40(最接近原点的 K 个点 K Closest Points to Origin)

154 阅读1分钟

最接近原点的 K 个点(K Closest Points to Origin)

LeetCode传送门973. 最接近原点的 K 个点

原题

我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。

(这里,平面上两点之间的距离是欧几里德距离。)

你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。

Given an array of points where points[i] = [xi, yi] represents a point on the X-Y plane and an integer k, return the k closest points to the origin (0, 0).

The distance between two points on the X-Y plane is the Euclidean distance (i.e., √(x1 - x2)2 + (y1 - y2)2).

You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in).

Example

Input: points = [[1,3],[-2,2]], k = 1
Output: [[-2,2]]
Explanation:
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].

Input: points = [[3,3],[5,-1],[-2,4]], k = 2
Output: [[3,3],[-2,4]]
Explanation: The answer [[-2,4],[3,3]] would also be accepted.

Constraints:

  • 1<=k<=points.length<=1041 <= k <= points.length <= 10^4
  • 104<xi,yi<104-10^4 < xi, yi < 10^4

思考线


解题思路

看到最大的前K位或者最小的前K位之类的问题,本能告诉我,可以用大小顶堆来做。

稍微改写一下上一期的关于小顶堆的解法,我们这次用大顶堆来实现。

function kClosest(points: number[][], k: number): number[][] {
    const maxHeap = new Heap([], (p1, p2) => {
        const l1 = Math.sqrt(Math.pow(p1[0], 2) + Math.pow(p1[1], 2));
        const l2 = Math.sqrt(Math.pow(p2[0], 2) + Math.pow(p2[1], 2));
        return l2 - l1 > 0;
    });
    for(let i = 0; i < points.length;i ++) {
        if(maxHeap.size() < k) {
            maxHeap.offer(points[i]);
        } else {
            const top = maxHeap.peek();
            const li = Math.sqrt(Math.pow(points[i][0], 2) + Math.pow(points[i][1], 2));
            const ltop = Math.sqrt(Math.pow(top[0], 2) + Math.pow(top[1], 2));
            if(ltop > li) {
                maxHeap.data[0] = points[i];
                maxHeap.bubbleDown(0);
            }
        }
    }
    const res = [];
    while(k--) {
        res.push(maxHeap.poll());
    }
    return res;


};
type dHash = number[]
class Heap {
    data: dHash[]
    comparator: (a: number[], b: number[]) => boolean
    constructor(data = [], comparator) {
        this.data = data;
        this.comparator = comparator;
        this.heapify();
    }
    heapify() {
        if (this.size() <= 1) return;
        for (let i = 1; i < this.size(); i++) {
            this.bubbleUp(i);
        }

    }

    bubbleUp(index) {
        while (index > 0) {
            const parent = (index - 1) >> 1;
            if (this.comparator(this.data[parent], this.data[index])) {
                this.swap(parent, index);
                index = parent
            } else {
                break;
            }
        }
    }
    bubbleDown(index) {
        while (index < this.size() - 1) {
            const left = index * 2 + 1;
            const right = index * 2 + 2;
            let findIndex = index;
            if (left < this.size() && this.comparator(this.data[findIndex], this.data[left])) {
                findIndex = left;
            }
            if (right < this.size() && this.comparator(this.data[findIndex], this.data[right])) {
                findIndex = right;
            }
            if (findIndex !== index) {
                this.swap(findIndex, index);
                index = findIndex;
            } else {
                break;
            }
        }

    }
    offer(val) {
        this.data.push(val);
        this.bubbleUp(this.size() - 1);

    }
    peek() {
        return this.data[0];
    }
    poll() {
        if (!this.size()) return null
        const res = this.data.shift();
        if (this.size()) {
            this.data.unshift(this.data.pop());
            this.bubbleDown(0)
        }
        return res;

    }
    size(): number {
        return this.data.length;
    }
    swap(index1, index2) {
        [this.data[index2], this.data[index1]] = [this.data[index1], this.data[index2]];
    }
}

这就是我对本题的解法,如果有疑问或者更好的解答方式,欢迎留言互动。