683 字
3 分钟
合并 K 个升序链表

题目描述#

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

解题思路#

  1. 分治合并(最优)
    • 将链表数组划分为两半
    • 递归合并左右两半
    • 合并结果链表
  2. 最小堆方法
    • 建立最小堆存储所有链表头节点
    • 每次取堆顶节点加入结果链
    • 更新堆顶为该节点下一节点
  3. 顺序合并(基础)
    • 顺序合并相邻链表
    • 重复合并直至单链表
  4. 虚拟头节点
    • 统一处理链表头节点
    • 简化边界条件处理

关键洞察#

  1. 分治效率核心
    • 两两合并避免高复杂度
    • 合并次数从O(k)降为O(log k)
  2. 堆选择原理
    • 堆优化最小节点获取效率
    • 每次操作时间复杂度O(log k)
  3. 空间复杂度对比
    • 分治法仅需递归栈空间
    • 堆方法需额外O(k)空间
  4. 合并顺序影响
    • 顺序合并会重复处理长链表
    • 分治合并保证平衡处理

复杂度分析#

方法时间复杂度空间复杂度说明
顺序合并O(k²·n)O(1)k为链表数,n为平均长度
分治合并O(kn log k)O(log k)递归栈深度
堆(优先队列)O(kn log k)O(k)堆中最多存储k个节点

代码实现#

/**
* 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) {
if (lists.length === 0) return null;
if (lists.length === 1) return lists[0];
const n = lists.length;
const half = Math.floor(n / 2);
let leftHead = mergeKLists(lists.slice(0, half));
let rightHead = mergeKLists(lists.slice(half));
let dummy = new ListNode();
let temp = dummy;
while (leftHead && rightHead) {
if (leftHead.val > rightHead.val) {
temp.next = rightHead;
rightHead = rightHead.next;
} else {
temp.next = leftHead;
leftHead = leftHead.next;
}
temp = temp.next;
}
temp.next = leftHead || rightHead;
return dummy.next;
};

实际应用场景#

  1. 多路归并排序:外部排序中的多路归并`
  2. 任务调度:合并多个有序任务队列`
  3. 数据库优化:合并多个索引列表`
  4. 日志系统:合并多个来源的有序日志`

变种:迭代分治合并#

const mergeKListsIterative = (lists) => {
if (!lists.length) return null;
while (lists.length > 1) {
const mergedLists = [];
for (let i = 0; i < lists.length; i += 2) {
const l1 = lists[i];
const l2 = i + 1 < lists.length ? lists[i + 1] : null;
mergedLists.push(mergeTwoLists(l1, l2));
}
lists = mergedLists;
}
return lists[0];
};
// 空间复杂度优化为O(1)
function mergeTwoLists(head1,head2){
const dummy = new ListNode();
let temp = dummy,temp1= head1,temp2 = head2;
while(temp1&&temp2){
if(temp1.val<temp2.val){
temp.next = temp1;
temp1 = temp1.next
}else{
temp.next = temp2;
temp2 = temp2.next
}
temp = temp.next;
}
temp.next = temp1 || temp2;
return dummy.next;
}

相似题目#

合并 K 个升序链表
https://website-truelovings-projects.vercel.app/posts/algorithms/合并-k-个升序链表/
作者
欢迎来到StarSky的网站!
发布于
2025-08-24
许可协议
CC BY-NC-SA 4.0