【问题标题】:Find the K closest points to the origin (0, 0)找到离原点最近的 K 个点 (0, 0)
【发布时间】:2019-06-29 20:48:32
【问题描述】:

问题是,给定一个坐标列表,确定离原点最近的 k 个坐标的数量。

我已经能够确定点和原点之间的距离,但是在过滤最近的 k 点时,我迷路了。我决定将此逻辑放在第二个 for 循环中,将距离数组从最近到最远排序,然后推送小于 K 的值。

function kClosest(points, k) {
    let length = [];
    let arr = [];
    let result = [];
    let a = 0;
    let b = 0;

    for (let i = 0; i < points.length; i++) {
        a = points[i][0]; //x coord
        b = points[i][1]; //y coord (y will always be second number or '1')
        length.push(parseFloat(calcHypotenuse(a, b).toFixed(4)))
        arr.push([points[i], length[i]])
    }

    function calcHypotenuse(a, b) {
        return (Math.sqrt((a * a) + (b * b)));
    }

    for (let i = 0; i < k; i++) {
        arr = arr.sort();
        result.push(arr[i][0])
    }
    return result;
}



console.log(kClosest([
    [-5, 4],
    [-6, -5],
    [4, 6]
], K = 2))

预期输出:[-5, 4], [4, 6] // 我有 [-5, 4], [-6, -5]

【问题讨论】:

标签: javascript arrays algorithm loops return


【解决方案1】:

对整个数组进行排序是一种浪费,甚至不可能。这是浪费的,因为问题没有要求所有元素的总排序,甚至没有 k 元素。使用基于比较的排序进行排序需要O(n log(n)) 时间。更一般地说,如果输入是一个数字流,则将它们全部存储在内存中并对其进行排序甚至是不可能的。

我对 JavaScript 了解不多,但在一般算法领域,我们可以使用以下 2 种方法之一更快地解决此问题:

  1. 使用 Max Priority Queue:创建一个最大 PQ,并根据与原点的距离进行排序。继续在最大 PQ 中插入元素,每当大小超过 k 时,删除顶部元素(最大值)。最后,PQ 将具有k 最小的元素。空间复杂度:O(k),时间复杂度:O(n log(k)),对于k &lt;&lt; n,可能接近O(n)
  2. 使用Quick-select:在输入上运行快速选择k次。这假设输入适合内存(空间O(n)),但运行时间为O(nk),对于k &lt;&lt; n,可能接近O(n)

【讨论】:

    【解决方案2】:

    我建议为此使用自定义排序 - 您可以传递 Array.sort() 一个比较函数,如下所示:

    function kClosest(points, k) {
    
        //sorts the array in place
        points.sort((point1, point2) => {
            const distanceFromOrigin1 = getDistanceFromOrigin(point1);
            const distanceFromOrigin2 = getDistanceFromOrigin(point2);
    
            //sort by distance from origin, lowest first
            return distanceFromOrigin1 - distanceFromOrigin2;
        });
    
        //returns first k elements
        return points.slice(0, k);
    }
    
    function getDistanceFromOrigin(point) {
        const [x, y] = point; //array destructuring
        return (x*x) + (y*y);
    }
    
    console.log(kClosest([
        [-5, 4],
        [-6, -5],
        [4, 6]
    ], 2))

    有关自定义排序的更多详细信息,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

    【讨论】:

    • 您好,邓肯,感谢您的建议。当我去实施它时,它成功了一半。问题是我的“arr”数组。由于它同时保存点/坐标和点到原点的长度,所以当我将 arr 传递给 sort 函数时,我得到相同的结果。但是,当我将 arr 简化为仅包含长度 [i] 时,我得到一个排序长度值的数组,这很好,但是如何将这些排序长度与原始坐标相关联呢?这就是我现在所处的位置。
    • 你真的不需要再做那些事情了——你可以直接对传入的points数组进行排序,不需要将长度存储在单独的数组中。长度仅在排序过程中计算(作为getDistanceFromOrigin() 函数实现)。
    • 为了澄清,我将扩展我的答案以包含完整的解决方案。
    • return 语句和上面的注释中有一个神奇的数字 2。 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多