1.题目描述
给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入: lists = [[1,4,5],[1,3,4],[2,6]]
输出: [1,1,2,3,4,4,5,6]
解释: 链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入: lists = []
输出: []
示例 3:
输入: lists = [[]]
输出: []
2.解题思路(小顶堆法)
核心思想是用小顶堆维护所有链表的 “当前待选最小节点”,每次取堆顶(全局最小)构建结果链表,具体步骤:
-
自定义小顶堆规则:C++ 优先队列默认是大顶堆,需自定义比较器,让堆按节点值升序排列(小值优先出堆)。
-
初始化堆:遍历所有链表,将每个非空链表的头节点加入堆中(空链表跳过)。
-
构建结果链表:
- 用哨兵节点(dummy) 简化头节点处理,避免空指针问题。
- 循环取出堆顶节点(当前最小节点),将其接入结果链表尾部。
- 若该节点的下一个节点非空,将下一个节点加入堆中(补充待选节点)。
-
终止条件:堆为空时,所有节点合并完成,返回哨兵节点的 next(结果链表头)。
3.代码实现
**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
struct CompareNode{
bool operator()(ListNode* a,ListNode* b){
return a->val > b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
//1.初始化小顶堆
priority_queue<ListNode*,vector<ListNode*>,CompareNode> minHeap;
//2.将所有非空链表的头节点加入堆
for(ListNode* head : lists){
if(head != nullptr){
minHeap.push(head);
}
}
//3.哨兵节点
ListNode dummy(0);
ListNode* curr = &dummy;
//4.循环取堆顶,构建结果链表
while(!minHeap.empty()){
//取出当前最小节点
ListNode* minNode = minHeap.top();
minHeap.pop();
//将最小节点接入结果链表
curr->next = minNode;
curr = curr->next;
//若该节点有下一个节点,加入堆中
if(minNode->next != nullptr){
minHeap.push(minNode->next);
}
}
return dummy.next;
}
};