[路飞]_leetcode-973-最接近原点的 K 个点

简介: leetcode-973-最接近原点的 K 个点

网络异常,图片无法展示
|


[题目地址][B站地址]


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


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


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


示例 1:


输入: points = [[1,3],[-2,2]], K = 1
输出: [[-2,2]]
解释:
(1, 3) 和原点之间的距离为 sqrt(10),
(-2, 2) 和原点之间的距离为 sqrt(8),
由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。
我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]。
复制代码


示例 2:


输入: points = [[3,3],[5,-1],[-2,4]], K = 2
输出: [[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也会被接受。)
复制代码



提示:


  1. 1 <= K <= points.length <= 10000
  2. -10000 < points[i][0] < 10000
  3. -10000 < points[i][1] < 10000


解题思路


本题中每个点到原点的之间的距离为两坐标值的平方和的开方。所以两坐标值的平方和越小,则该点距离原点越近。


所以我们只需要找到坐标轴值平方和最小的 k 个点即可。


sort


可以通过以上信息对输入数组进行降序排序,返回排序后的前 k 个元素组成的数组即可。


代码实现


var kClosest = function(points, k) {
  // 对输入数组升序排序
  points.sort((a,b) => (a[0]*a[0]+a[1]*a[1])-(b[0]*b[0]+b[1]*b[1]))
  // 返回排序后的前 k 个元素
  return points.slice(0,k)
};
复制代码


大顶堆


涉及到要维护最值的问题,都可以利用堆来做。


这里因为要维护前 k 个最小值,所以需要一个大顶堆。


循环输入数组,当堆中元素数量小于 k 个或者当前元素小于堆顶元素的时候,将当前元素插入堆中。


如果插入后堆中元素数量超过 k 个,弹出堆顶元素。


最后返回堆中的元素即可。


代码实现


// 大顶堆
class BigHeap{
  constructor(){
    this.arr = [];
    this.size = 0;
  }
  // 插入操作
  push(item){
    this.arr.push(item);
    this.size++;
    // 插入后自下向上平衡调整
    if(this.size>1){
      let cur = this.size-1,
      parent = (cur-1)>>1;
      while(cur>0&&compare(this.arr[parent],this.arr[cur])){
        [this.arr[parent],this.arr[cur]] =
        [this.arr[cur],this.arr[parent]]
        cur = parent,parent = (cur-1)>>1;
      }
    }
  }
  // 弹出操作
  pop(){
    this.arr[0] = this.arr.pop();
    this.size--;
    // 弹出后自上向下平衡调整
    let cur = 0,childl = 1,childr = 2;
    while(
      (childl<this.size&&compare(this.arr[cur],this.arr[childl])) ||
      (childr<this.size&&compare(this.arr[cur],this.arr[childr]))
    ){
      if(childr<this.size&&compare(this.arr[childl],this.arr[childr])){
        [this.arr[cur],this.arr[childr]] =
        [this.arr[childr],this.arr[cur]]
        cur = childr;
      }else{
        [this.arr[cur],this.arr[childl]] =
        [this.arr[childl],this.arr[cur]]
        cur = childl;
      }
      childl = cur*2+1,childr = cur*2+2;
    }
  }
  // 获取堆顶元素
  top(){
    return this.arr[0]
  }
}
// compare函数
function compare(a,b){
  return (a[0]*a[0]+a[1]*a[1])<(b[0]*b[0]+b[1]*b[1])
}
var kClosest = function(points, k) {
  // 获取大顶堆实例
  const heap = new BigHeap();
  // 遍历输入数组
  for(let i = 0;i<points.length;i++){
    // 将前 k 个最小的元素保存在堆中
    if(heap.size<k || compare(points[i],heap.top())){
      heap.push(points[i])
      if(heap.size>k) heap.pop();
    }
  }
  // 返回堆中的元素
  return heap.arr;
};
复制代码


至此我们就完成了 leetcode-973-最接近原点的 K 个点


如有任何问题或建议,欢迎留言讨论!

相关文章
|
8月前
|
机器人
【Leetcode -657.机器人能否返回原点 -674.最长连续递增序列】
【Leetcode -657.机器人能否返回原点 -674.最长连续递增序列】
25 0
|
18天前
|
存储 算法 数据挖掘
LeetCode第十六题: 掌握双指针技巧 最接近的三数之和 【python】
LeetCode第十六题: 掌握双指针技巧 最接近的三数之和 【python】
|
1月前
leetcode-16:最接近的三数之和
leetcode-16:最接近的三数之和
30 0
【LeetCode-每日一题】-16. 最接近的三数之和
【LeetCode-每日一题】-16. 最接近的三数之和
|
6月前
|
Java
1657. 确定两个字符串是否接近 --力扣 --JAVA
如果可以使用以下操作从一个字符串得到另一个字符串,则认为两个字符串 接近 : 操作 1:交换任意两个 现有 字符。 例如,abcde -> aecdb 操作 2:将一个 现有 字符的每次出现转换为另一个 现有 字符,并对另一个字符执行相同的操作。 例如,aacabb -> bbcbaa(所有 a 转化为 b ,而所有的 b 转换为 a ) 你可以根据需要对任意一个字符串多次使用这两种操作。 给你两个字符串,word1 和 word2 。如果 word1 和 word2 接近 ,就返回 true ;否则,返回 false 。
32 0
|
11月前
LeetCode: 16. 最接近的三数之和 | 双指针专题
【LeetCode: 16. 最接近的三数之和 | 双指针专题 】
41 1
|
11月前
|
存储 算法 Python
【力扣算法01】之最接近的三数之和
【力扣算法01】之最接近的三数之和
63 0
|
12月前
|
测试技术 C++
力扣16-最接近的三数之和&力扣18-四数之和
力扣16-最接近的三数之和&力扣18-四数之和
63 0
|
12月前
|
算法 安全 Swift
LeetCode - #16 最接近的三数之和
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
leetcode:16.最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
44 0