23. Merge k Sorted Lists
Last updated
Last updated
time: O(nk), n is length of lists, k is the length of largest ListNode
space: O(1), use reference
/**
* 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 minHeap = new Heap([], (a, b) => a[1].val <= b[1].val);
for (let i = 0; i < lists.length; i++) {
const node = lists[i];
if (node !== null) {
minHeap.insert([i, node]);
}
}
const prev = new ListNode(-1, null);
let currentNode = prev;
while (minHeap.size !== 0) {
const [index, minNode] = minHeap.remove();
currentNode.next = minNode;
currentNode = currentNode.next;
lists[index] = lists[index].next;
if (lists[index] !== null) {
minHeap.insert([index, lists[index]]);
}
}
return prev.next;
};
class Heap {
constructor(arr, predicate = (a, b) => a <= b) {
this.predicate = predicate;
this.size = arr.length;
this.heap = this.buildHeap(arr);
}
buildHeap(arr) {
let currentIndex = Math.floor((arr.length - 1 - 1) / 2);
while (currentIndex >= 0) {
this.siftDown(arr, currentIndex, arr.length - 1);
currentIndex--;
}
return arr;
}
insert(v) {
this.heap.push(v);
this.size++;
this.siftUp(this.heap, this.heap.length - 1);
}
remove(v) {
this.swap(this.heap, 0, this.heap.length - 1);
const elementToRemove = this.heap.pop();
this.size--;
this.siftDown(this.heap, 0, this.heap.length - 1);
return elementToRemove;
}
siftUp(heap, currentIndex) {
let parentIndex = Math.floor((currentIndex - 1) / 2);
while (parentIndex >= 0) {
if (this.predicate(heap[parentIndex], heap[currentIndex])) {
break;
}
this.swap(heap, parentIndex, currentIndex);
currentIndex = parentIndex;
parentIndex = Math.floor((currentIndex - 1) / 2);
}
return heap;
}
siftDown(heap, currentIndex, endIndex) {
let left = currentIndex * 2 + 1;
while (left <= endIndex) {
let min = left;
const right = currentIndex * 2 + 2;
if (heap[right] !== undefined && this.predicate(heap[right], heap[min])) {
min = right;
}
if (this.predicate(heap[currentIndex], heap[min])) break;
this.swap(heap, currentIndex, min);
currentIndex = min;
left = currentIndex * 2 + 1;
}
return heap;
}
clear() {
this.heap = [];
this.size = 0;
}
swap(arr, a, b) {
[arr[b], arr[a]] = [arr[a], arr[b]];
}
}