LeetCode-23.[合并K个升序链表]

6 阅读2分钟

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.解题思路(小顶堆法)

核心思想是用小顶堆维护所有链表的 “当前待选最小节点”,每次取堆顶(全局最小)构建结果链表,具体步骤:

  1. 自定义小顶堆规则:C++ 优先队列默认是大顶堆,需自定义比较器,让堆按节点值升序排列(小值优先出堆)。

  2. 初始化堆:遍历所有链表,将每个非空链表的头节点加入堆中(空链表跳过)。

  3. 构建结果链表

    • 哨兵节点(dummy) 简化头节点处理,避免空指针问题。
    • 循环取出堆顶节点(当前最小节点),将其接入结果链表尾部。
    • 若该节点的下一个节点非空,将下一个节点加入堆中(补充待选节点)。
  4. 终止条件:堆为空时,所有节点合并完成,返回哨兵节点的 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;
    }
};