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; //因为都要接到新建的链表后面
};
原文地址:https://www.cnblogs.com/oaoa/p/15037719.html