Leetcode 0023.Merge k Sorted Lists(python)
23. Merge k Sorted Lists
题目
You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.
Merge all the linked-lists into one sorted linked-list and return it.
Example 1:
1 | Input: lists = [[1,4,5],[1,3,4],[2,6]] |
Example 2:
1 | Input: lists = [] |
Example 3:
1 | Input: lists = [[]] |
题目大意
给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
你选用何种方法解题?
本题是“合并两个有序链表”的进阶版。核心难点在于如何高效地从 k 个链表中选择最小的节点。
| 方法 | 时间复杂度 | 空间复杂度 | 是否推荐 |
|---|---|---|---|
| 分治合并 | O(N log k) | O(log k) | 推荐 |
| 优先队列(最小堆) | O(N log k) | O(k) | 推荐 |
| 顺序合并 | O(kN) | O(1) | 不推荐 |
方法选择理由:
- 分治合并:将 k 个链表两两配对合并,类似归并排序。无需额外空间存储节点引用,递归栈空间较小。
- 优先队列(最小堆):维护一个大小为 k 的堆,每次获取最小节点。思路直观,适合需要动态维护最小值的场景。
- 顺序合并:像“冒泡”一样一个个合并,效率最低,容易被卡超时。
解题过程
问题分析
输入:包含 k 个升序链表的数组 lists。
输出:合并后的升序链表。
关键约束:
- 链表已按升序排列。
- 需要高效地找到当前
k个链表头节点中的最小值。
核心洞察
分治法:
- 类似归并排序的
merge阶段。 - 第一轮合并
lists[0]&lists[1],lists[2]&lists[3]... - 第二轮合并上一轮的结果,直到只剩一个链表。
- 每个节点参与的合并次数为
log k次。
- 类似归并排序的
优先队列(堆):
- 利用最小堆自动维护当前所有链表头节点的最小值。
- 每次从堆顶取出最小节点,将其后继节点加入堆。
- 每个节点入堆、出堆各一次,复杂度为
log k。
算法流程演示
分治法流程(以 lists = [L1, L2, L3, L4] 为例):
1 | Round 1: |
最小堆流程(以 lists = [[1,4,5],[1,3,4],[2,6]] 为例):
1 | 初始化堆:将各链表头节点入堆 -> Heap: [1, 1, 2] |
这些方法具体怎么运用?
方法一:分治合并(推荐)
核心逻辑:
- 迭代合并:使用
while循环,只要lists中不止一个链表就继续。 - 两两配对:在内层循环中,取出两个链表调用
mergeTwoLists。 - 更新列表:将合并后的结果放入新列表
merged,一轮结束后用merged替换lists。
边界情况处理:
- 如果
lists为空或长度为 0,返回None。 - 如果
lists长度为奇数,最后一个链表会落单,直接加入merged即可。
方法二:优先队列(最小堆)(推荐)
核心逻辑:
- 初始化堆:遍历
lists,将所有非空头节点加入堆。 - 构建结果链表:使用
dummy节点。 - 循环处理:
- 弹出堆顶最小节点
node。 - 将
node接到结果链表末尾。 - 若
node.next存在,将其加入堆。
- 弹出堆顶最小节点
Python 技巧:
- Python 的
heapq默认支持元组比较。如果节点值相同,元组第二个元素(索引)可用于打破平局。 - 自定义
__lt__方法可以让ListNode直接入堆(如本题代码所示)。
复杂度
设 $N$ 为所有链表中的节点总数,$k$ 为链表条数。
| 方法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 分治合并 | O(N log k) | O(log k) | 递归栈深度(迭代法可优化为 O(1)) |
| 优先队列 | O(N log k) | O(k) | 堆的大小最大为 k |
总结与最佳选择
最快算法:分治合并 和 优先队列 时间复杂度相同。
- 分治合并:不需要额外的堆空间,空间复杂度更优(不考虑递归栈时)。
- 优先队列:代码逻辑更符合直觉(“每次找最小”),但在 Python 中实现需要处理自定义比较或使用元组。
工程最优选择:
- 分治合并:面试首选,展示对归并思想的深入理解,且空间效率高。
- 优先队列:适合快速实现,逻辑直观。
Code
方法一:分治合并(推荐)
1 | from typing import List, Optional |
方法二:优先队列(最小堆)
1 | from typing import List, Optional |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.

