iT邦幫忙

2024 iThome 鐵人賽

DAY 18
0
佛心分享-刷題不只是刷題

刷題筆記系列 第 18

[Day18] K Closest Points to Origin

  • 分享至 

  • xImage
  •  

Given an array of points where points[i] = [xᵢ, yᵢ] 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)² + (y1 - y2)²).
You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in).

給定一個點陣列,其中 points[i] = [xᵢ, yᵢ] 表示 X-Y 平面上的一個點,以及一個整數 k,回傳離原點 (0, 0) 最近的 k 個點。

在 X-Y 平面上兩點之間的距離是歐幾里得距離(即 √((x1 - x2)² + (y1 - y2)²))。

你可以以任意排序回傳答案。答案保證是唯一的(除了排序以外)。

https://ithelp.ithome.com.tw/upload/images/20240830/20168667CPNuhNgy3v.png
https://ithelp.ithome.com.tw/upload/images/20240830/20168667sRH5dIgiOu.png


簡單的說,就是把陣列中的每一組的(x,y)算出距離原點的距離,找出k個最小的組合。這次改用max-heap,一樣先建立一個可以裝入k個元素的max-heap,然後再用for loop把剩餘的(x,y)組合(就是整個陣列扣除k組組合)比較距離原點的大小,只要距離比heap的根節點存放的組合還要小,則交換。

注意: 是比根節點小才跟根節點交換,必須讓heap的size保持在k,因為在這個max-heap裡面裝的就是我們要找的k隔離原點最近的組合們。

如此一來,這樣比到最後,直接把heap裡面的組合回傳就完成啦!

是不是很有趣呢? 昨天的題目要找第k個的元素,使用的是min-heap(最小堆積),但是今天要找k個最的組合,使用的卻是max-heap(最大堆積)。

來看程式碼吧

function kClosest(points, k) {
    const maxHeap = [];

    // 交换
    function swap(i, j) {
        [maxHeap[i], maxHeap[j]] = [maxHeap[j], maxHeap[i]];
    }

    // heapify 向上交換
    function heapifyUp(index) {
        const parentIndex = Math.floor((index - 1) / 2);
        if (parentIndex >= 0 && maxHeap[parentIndex][2] < maxHeap[index][2]) {
            swap(parentIndex, index);
            heapifyUp(parentIndex);
        }
    }

    // heapify 向上交換
    function heapifyDown(index) {
        const leftChildIndex = 2 * index + 1;
        const rightChildIndex = 2 * index + 2;
        let largest = index;

        if (leftChildIndex < maxHeap.length && maxHeap[leftChildIndex][2] > maxHeap[largest][2]) {
            largest = leftChildIndex;
        }

        if (rightChildIndex < maxHeap.length && maxHeap[rightChildIndex][2] > maxHeap[largest][2]) {
            largest = rightChildIndex;
        }

        if (largest !== index) {
            swap(index, largest);
            heapifyDown(largest);
        }
    }

    // 插入到heap中
    function insert(point) {
        maxHeap.push(point);
        heapifyUp(maxHeap.length - 1);
    }

    // 删除heap的根節點并保持heap的結構
    function removeTop() {
        if (maxHeap.length > 1) {
            swap(0, maxHeap.length - 1);
        }
        const removed = maxHeap.pop();
        heapifyDown(0);
        return removed;
    }

    // 遍歷所有點並build heap
    for (let [x, y] of points) {
        const dist = x * x + y * y; // 計算距離的平方
        insert([x, y, dist]);

        // 如果heap的大小超過 k,移除root根節點
        if (maxHeap.length > k) {
            removeTop();
        }
    }
    return maxHeap.map(item => [item[0], item[1]]);
}

上一篇
[Day17] Kth Largest Element in an Array
下一篇
[Day19] Patterns: Merge Intervals
系列文
刷題筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言