📅  最后修改于: 2023-12-03 14:49:55.428000             🧑  作者: Mango
在处理大量数据时,使用最小堆是一种常见且有效的方法。本文将介绍如何使用最小堆来合并 K 个已排序链表。这个问题可以使用多种方法来解决,但是在本文中,我们将专注于使用最小堆来完成此任务。
给定 K 个已排序链表,将它们合并成一个排序链表。例如,当 K = 3 时,给定的链表集合为:
[
1 -> 4 -> 5,
1 -> 3 -> 4,
2 -> 6
]
合并后的链表为 1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6。
使用最小堆可以使得合并 K 个已排序链表变得非常高效。它的基本思路是首先将每个链表的第一个节点插入到最小堆中。然后,从堆中取出最小元素,将它的下一个节点插入到堆中。重复此过程,直到所有节点都被插入到新链表中。
下面是使用最小堆的 JavaScript 代码。它使用了一个自定义的 ListNode 类来表示链表节点。函数 mergeKLists 接收一个链表数组,返回合并后的链表头节点。
class ListNode {
constructor(val, next = null) {
this.val = val;
this.next = next;
}
}
const mergeKLists = lists => {
const heap = new MinHeap();
const dummy = new ListNode(0);
let tail = dummy;
// Insert the first node of each list into the heap
for (const list of lists) {
if (list) heap.insert(list);
}
// Take the smallest node from the heap and insert its next node
while (!heap.isEmpty()) {
const node = heap.pop();
tail.next = node;
tail = tail.next;
if (node.next) heap.insert(node.next);
}
return dummy.next;
};
class MinHeap {
constructor() {
this.heap = [];
}
insert(val) {
this.heap.push(val);
this.bubbleUp(this.heap.length - 1);
}
pop() {
const min = this.heap[0];
const last = this.heap.pop();
if (this.heap.length) {
this.heap[0] = last;
this.bubbleDown(0);
}
return min;
}
isEmpty() {
return this.heap.length === 0;
}
bubbleUp(idx) {
if (idx === 0) return;
const pIdx = Math.floor((idx - 1) / 2);
if (this.heap[idx].val < this.heap[pIdx].val) {
[this.heap[idx], this.heap[pIdx]] = [this.heap[pIdx], this.heap[idx]];
this.bubbleUp(pIdx);
}
}
bubbleDown(idx) {
const [leftIdx, rightIdx] = [idx * 2 + 1, idx * 2 + 2];
const leftVal = this.heap[leftIdx]?.val;
const rightVal = this.heap[rightIdx]?.val;
const currentVal = this.heap[idx].val;
// If the current node is already smaller than its children, stop bubbling down
if (currentVal <= leftVal && currentVal <= rightVal) return;
// Otherwise, swap the current node with its smallest child
const swapIdx = leftVal < rightVal ? leftIdx : rightIdx;
[this.heap[idx], this.heap[swapIdx]] = [this.heap[swapIdx], this.heap[idx]];
this.bubbleDown(swapIdx);
}
}
在本文中,我们介绍了如何使用最小堆来合并 K 个已排序链表。这个算法的时间复杂度为 O(N log K),其中 N 是所有链表中节点的总数。对于大型数据集,使用最小堆将大大提高算法的效率。