23. 合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 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.length0 <= k <= 10^40 <= lists[i].length <= 500-10^4 <= lists[i][j] <= 10^4lists[i]按 升序 排列lists[i].length的总和不超过10^4
/**
* 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 k = lists.length;
const heap = new Heap((a, b) => a.val < b.val);
const result = new ListNode();
let p = result;
for (let i = 0; i < k; i++) {
if(lists[i]) {
heap.push(lists[i]);
}
}
while (heap.getTop()) {
const { val, next } = heap.pop();
if (next) {
heap.push(next);
}
const node = new ListNode(val, null);
p.next = node;
p = node;
}
return result.next;
};
class Heap {
constructor(compare) {
this.nodeList = [];
this.compare = typeof compare === 'function' ? compare : this.defaultCompare;
}
defaultCompare(a, b) {
return a > b;
}
getSize() {
return this.nodeList.length;
}
getTop() {
if (this.nodeList.length === 0) {
return null;
}
return this.nodeList[0];
}
push(value) {
this.nodeList.push(value);
this.up(this.nodeList.length - 1);
}
up(index) {
const { compare, parent, nodeList } = this;
let curIndex = index;
let parentIndex = parent(curIndex);
while (curIndex > 0 && compare(nodeList[curIndex], nodeList[parentIndex])) {
const temp = nodeList[curIndex];
nodeList[curIndex] = nodeList[parentIndex];
nodeList[parentIndex] = temp;
curIndex = parentIndex;
parentIndex = parent(curIndex);
}
}
parent(index) {
return index % 2 === 0 ? index / 2 - 1 : (index - 1) / 2;
}
pop() {
if (this.nodeList.length === 0) {
return null;
}
const top = this.nodeList[0];
this.nodeList[0] = this.nodeList[this.nodeList.length - 1];
this.nodeList.pop();
this.down(0);
return top;
}
down(index) {
const { compare, left, right, nodeList } = this;
let curIndex = index;
while (left(curIndex) < nodeList.length) {
let target = left(curIndex);
if (right(curIndex) < nodeList.length && compare(nodeList[right(curIndex)], nodeList[left(curIndex)])) {
target = right(curIndex);
}
if (compare(nodeList[curIndex], nodeList[target])) {
break;
}
const temp = nodeList[curIndex];
nodeList[curIndex] = nodeList[target];
nodeList[target] = temp;
curIndex = target;
}
}
left(index) {
return index * 2 + 1;
}
right(index) {
return index * 2 + 2;
}
}