题目

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

示例

  1. (转自leetcode)
  2. 输入:points = [[1,3],[-2,2]], K = 1
  3. 输出:[[-2,2]]
  4. 解释:
  5. (1, 3) 和原点之间的距离为 sqrt(10),
  6. (-2, 2) 和原点之间的距离为 sqrt(8),
  7. 由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。
  8. 我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]
  9. 来源:力扣(LeetCode
  10. 链接:https://leetcode-cn.com/problems/k-closest-points-to-origin
  11. 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

提示

  • 初中数学中的直角斜边的公式(a平方 + b平方 = c平方)
  • js内置一个API,(Math.hypot(a, b) = c).方法返回所有参数的平方和的平方根

    所以

    最接近原点的 K 个点(leetcode) - 图1
    求的就是上图中的两条斜线 ```javascript 斜线 (-2, 2)到原点设为c1 斜线 (1, 3)到原点设为c2

c1 = Math.sqrt(Math.pow(-2, 2) + Math.pow(-2, 2), 2); c2 = Math.sqrt(Math.pow(1, 2) + Math.pow(3, 2), 2);

// Math.hypot来表示就是, 简便了很多 c1 = Math.hypot(-2, 2); c2 = Math.hypot(1, 3);

  1. <a name="c7nTU"></a>
  2. ### 实现
  3. - 使用大顶堆来写
  4. ```javascript
  5. /**
  6. * @param {number[][]} points
  7. * @param {number} k
  8. * @return {number[][]}
  9. */
  10. var kClosest = function(points, k) {
  11. const distanceMap = transform(points);
  12. const heap = [];
  13. distanceMap.forEach((item) => {
  14. if (heap.length < k) {
  15. push(heap, item);
  16. } else {
  17. if (heap[0].distance > item.distance) {
  18. pop(heap);
  19. push(heap, item);
  20. }
  21. }
  22. });
  23. return heap.map((item) => points[item.key]);
  24. };
  25. /**
  26. * 将计算出点于原点的距离
  27. */
  28. function transform(points) {
  29. return points.map((point, index) => {
  30. return {
  31. key: index,
  32. distance: Math.hypot(point[0], point[1]),
  33. };
  34. });
  35. };
  36. // 大顶堆
  37. // 将距离最远的放入堆顶
  38. // 当堆内达到指定的数量后,比较堆顶于当前推入元素大小
  39. function pop(heap) {
  40. if (heap.length === 0) {
  41. return;
  42. }
  43. const first = heap[0];
  44. const last = heap.pop();
  45. if (first !== last) {
  46. heap[0] = last;
  47. siftDown(heap, last, 0);
  48. }
  49. return first;
  50. }
  51. function push(heap, node) {
  52. const len = heap.length;
  53. heap.push(node);
  54. siftUp(heap, node, len);
  55. }
  56. function compare(a, b) {
  57. return a.distance - b.distance;
  58. };
  59. function siftUp(
  60. heap,
  61. node,
  62. i,
  63. ) {
  64. let index = i;
  65. while(index > 0) {
  66. const parentIndex = (index - 1) >>> 1;
  67. const parent = heap[parentIndex];
  68. if (compare(node, parent) > 0) {
  69. heap[parentIndex] = node;
  70. heap[index] = parent;
  71. index = parentIndex;
  72. } else {
  73. return;
  74. }
  75. }
  76. };
  77. function siftDown(
  78. heap,
  79. node,
  80. i,
  81. ) {
  82. const length = heap.length;
  83. const halfIndex = length >>> 1;
  84. let parentIndex = i;
  85. while(parentIndex < halfIndex) {
  86. const leftIndex = (parentIndex << 1) + 1;
  87. const left = heap[leftIndex];
  88. const rightIndex = leftIndex + 1;
  89. const right = heap[rightIndex];
  90. if (compare(left, node) > 0) {
  91. if (rightIndex < length && compare(right, left) > 0) {
  92. heap[rightIndex] = node;
  93. heap[parentIndex] = right;
  94. parentIndex = rightIndex;
  95. } else {
  96. heap[leftIndex] = node;
  97. heap[parentIndex] = left;
  98. parentIndex = leftIndex;
  99. }
  100. } else if (rightIndex < length && compare(right, node) > 0) {
  101. heap[rightIndex] = node;
  102. heap[parentIndex] = right;
  103. parentIndex = rightIndex;
  104. } else {
  105. return;
  106. }
  107. }
  108. };