最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • LeetCode题解:剑指 Offer 40. 最小的k个数,二叉堆,JavaScript,详细注释

    正文概述 掘金(LeeChen)   2020-12-30   467

    原题链接:leetcode-cn.com/problems/zu…

    解题思路:

    1. 该题可使用堆解决,利用了堆能够快速插入和取出元素,并始终能够按要求排序的特点。
    2. 使用JavaScript实现一个二叉堆,并将数组元素依次存入堆中,之后再依次取出k个元素即可。
    /**
     * @param {number[]} arr
     * @param {number} k
     * @return {number[]}
     */
    var getLeastNumbers = function(arr, k) {
      let result = []; // 存储结果
      let heap = new BinaryHeap((a, b) => a - b); // 创建一个堆,元素由小到大排序
    
      // 将数组元素都插入堆
      for (let i = 0; i < arr.length; i++) {
        heap.insert(arr[i]);
      }
    
      // 从堆中按顺序取出k个元素
      for (let j = 0; j < k; j++) {
        result.push(heap.deleteHead());
      }
    
      return result;
    };
    
    class BinaryHeap {
      constructor(compare) {
        this.data = []; // 使用数组存储堆
        this.compare = compare; // 堆元素的排序函数
      }
    
      // 向堆插入元素
      insert(value) {
        this.insertAt(this.data.length, value);
      }
    
      // 将元素插入到index位置
      insertAt(index, value) {
        // 先将元素插入到指定的位置
        this.data[index] = value;
        let fatherIndex = index;
        // 对比当前节点与其父节点,如果当前节点更小就交换它们
        // Math.floor((index - 1) / 2)是父节点在数组中的索引
        while (
          index > 0 &&
          // 使用传入的对比函数比较大小
          this.compare(
            value,
            this.data[(fatherIndex = Math.floor((index - 1) / 2))]
          ) < 0
        ) {
          // 将父节点移动到当前位置
          this.data[index] = this.data[fatherIndex];
          // 将插入的值移动到父节点位置
          this.data[fatherIndex] = value;
          // 更新索引为父节点索引,继续下一次循环
          index = fatherIndex;
        }
      }
    
      // 删除最大节点
      deleteHead() {
        return this.delete(0);
      }
    
      // 将指定位置的元素删除
      delete(index) {
        // 如果堆为空,则不进行删除操作
        if (this.data.length === 0) {
          return;
        }
    
        let value = this.data[index]; // 将要删除的元素缓存
        let parent = index; // 以当前元素为起始,向下整理堆
    
        // 不断向子节点整理堆,每次循环将子节点中经过compare方法对比后较大者与父节点调换
        while (parent < this.data.length) {
          let left = parent * 2 + 1; // 左子节点索引
          let right = parent * 2 + 2; // 右子节点索引
    
          // 没有左子节点,表示当前节点已经是最后一个节点
          if (left >= this.data.length) {
            break;
          }
    
          // 没有右子节点,则直接将左子节点提前到父节点即可
          // 该左子节点即为最后一个节点
          if (right >= this.data.length) {
            this.data[parent] = this.data[left];
            parent = left;
            break;
          }
    
          // 使用compare方法比较左右子节点的大小,更大的补到父节点
          if (this.compare(this.data[left], this.data[right]) < 0) {
            // 由于被删除的节点已保存,此处只需要将子节点复制到当前父节点即可
            this.data[parent] = this.data[left];
            // 完成移动后将父节点指针移动到子节点,供下一次整理使用
            parent = left;
          } else {
            this.data[parent] = this.data[right];
            parent = right;
          }
        }
    
        // 查看最后的空位是不是最后的叶子节点
        if (parent < this.data.length - 1) {
          // 如果还未整理到叶子节点,则继续向下整理
          this.insertAt(parent, this.data.pop());
        } else {
          // 当完成整理时,最后一个节点即为多于元素,直接弹出数组即可
          this.data.pop();
        }
    
        // 返回被删除的元素
        return value;
      }
    }
    

    起源地下载网 » LeetCode题解:剑指 Offer 40. 最小的k个数,二叉堆,JavaScript,详细注释

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元