zoukankan      html  css  js  c++  java
  • 23、合并K个升序链表 | JS堆

    给你一个链表数组,每个链表都已经按升序排列。

    请你将所有链表合并到一个升序链表中,返回合并后的链表。

    示例 1:

    输入:lists = [[1,4,5],[1,3,4],[2,6]]
    输出:[1,1,2,3,4,4,5,6]
    解释:链表数组如下:
    [
    1->4->5,
    1->3->4,
    2->6
    ]
    将它们合并到一个有序链表中得到。
    1->1->2->3->4->4->5->6


    示例 2:

    输入:lists = []
    输出:[]


    示例 3:

    输入:lists = [[]]
    输出:[]
     

    提示:

    k == lists.length
    0 <= k <= 10^4
    0 <= lists[i].length <= 500
    -10^4 <= lists[i][j] <= 10^4
    lists[i] 按 升序 排列
    lists[i].length 的总和不超过 10^4

    class MinHeap {
      constructor(){
        this.heap = [];
      }
      swap(i1, i2){
        const temp = this.heap[i1];
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;
      }
      getParentIndex(i){  //获取父节点的值
        return (i-1) >> 1;  //二进制右移相当于除以2
      }
      getLeftIndex(i) {  //获取左结点
        return i * 2 + 1;
      }
      getRightIndex(i) {  //获取右结点
        return i * 2 + 2;
      }
    
      shiftUp(index){   //需要让父节点不断小于它的子节点
        if(index == 0){ return; }  //如果已经是根结点了就不用找了
        const parentIndex = this.getParentIndex(index);
        if(this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val){
          this.swap(parentIndex, index);  //如果父节点的值大于子节点则进行交换
          this.shiftUp(parentIndex)
        }
      }
      insert(value){  //插入,添加的方法
        this.heap.push(value);
        this.shiftUp(this.heap.length - 1);  //shiftUp就是上移操作,接收参数是上移时的下标
      }
      shiftDown(index){  //下移节点,直到子节点都大于当前节点的值
        // 需要获取它的左右子节点
        const leftIndex = this.getLeftIndex(index);
        const rightIndex = this.getRightIndex(index);
        if(this.heap[leftIndex] && this.heap[leftIndex].val < this.heap[index].val){  //小顶堆,父节点小于子节点
          this.swap(leftIndex, index);
          this.shiftDown(leftIndex);  //迭代,直到找到合适的位置
        }
        if(this.heap[rightIndex] && this.heap[rightIndex].val < this.heap[index].val){  //小顶堆,父节点小于子节点
          this.swap(rightIndex, index);
          this.shiftDown(rightIndex);  //迭代,直到找到合适的位置
        }
      }
    
      pop(){   //下移方法
        if(this.size() === 1) return this.heap.shift();
        const top = this.heap[0];
        this.heap[0] = this.heap.pop();  // 把数组的最后一位转移到头部,相当于变相删除堆顶
        this.shiftDown(0);  //传什么下标,就对那个进行下移操作
        return top;  //返回堆顶
      }
      peek(){ //获取堆顶,返回数组的头部
        return this.heap[0];
      }
      size(){  // 获取堆的大小
        return this.heap.length;
      }
    }
    /**
     * Definition for singly-linked list.
     * function ListNode(val, next) {
     *     this.val = (val===undefined ? 0 : val)
     *     this.next = (next===undefined ? null : next)
     * }
     */
    /**
     * @param {ListNode[]} lists
     * @return {ListNode}
     */
    var mergeKLists = function(lists) {
        const res = new ListNode(0);
        let p = res;
        const h = new MinHeap();
        lists.forEach(l => {
            if(l) h.insert(l);
        })
        while(h.size()){  //堆有值的情况下不断的循环
            const n = h.pop();
            p.next = n;
            p = p.next;  //方便接后面的结点
            if(n.next) h.insert(n.next);  //把下一个结点插入
        }
        return res.next; //因为都要接到新建的链表后面
    };
  • 相关阅读:
    数据流控制
    转:简单的Mysql主从复制设置
    转:CentOS---网络配置详解
    Linux-vim学习入门
    Linux图形界面与字符界面切换
    转:MySQL表名不区分大小写
    CentOS6.5_x86安装Mysql5.5.49
    Linux的环境变量设置和查看
    Linux防火墙的关闭和开启
    Linux command not found 问题解释
  • 原文地址:https://www.cnblogs.com/oaoa/p/15037719.html
Copyright © 2011-2022 走看看