1. 问题背景与核心挑战
合并K个升序链表是算法面试中的经典问题,它考察了对数据结构、指针操作和分治思想的理解。这个问题可以看作是合并两个有序链表的进阶版本,但当链表数量增加时,直接套用两两合并的方法会导致性能急剧下降。
在实际开发中,这类场景常见于:
- 多路归并排序的实现
- 分布式系统中合并多个有序数据流
- 数据库多索引扫描的结果合并
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解决方案设计思路
2.1 暴力解法及其缺陷
最直观的解法是循环遍历所有链表头节点,每次找出最小值节点。这种方法的时间复杂度是O(NK),其中N是节点总数,K是链表数量。当K很大时(比如K=10000),这种方法的性能将无法接受。
提示:假设每个链表平均长度是M,那么N=K*M,时间复杂度实际上是O(K²M)
2.2 堆的优化思路
使用最小堆(优先队列)可以将每次查找最小值的时间从O(K)降到O(logK)。具体原理是:
- 初始时将所有链表头节点入堆
- 每次取出堆顶(当前最小)节点加入结果链表
- 将该节点的下一个节点(如果存在)放入堆中
- 重复直到堆为空
这种方法的时间复杂度是O(NlogK),空间复杂度是O(K)(堆的大小)。
3. 代码实现详解
3.1 数据结构定义
cpp复制struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
3.2 自定义比较器
C++的priority_queue默认是大顶堆,我们需要通过自定义比较器实现小顶堆:
cpp复制struct Compare {
bool operator()(const ListNode* a, const ListNode* b) {
return a->val > b->val; // 注意这里是大于号
}
};
注意:比较函数返回true表示a应该排在b
