给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 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; //因为都要接到新建的链表后面 };