LeetCodehot100-23合并 K 个升序链表

特性 queue priority_queue
顺序 FIFO(先进先出) 按优先级
访问 front/back top
底层 deque/list 堆(vector)

双向队列:deque

priority_queue 是 C++ 标准库中的优先队列 容器适配器。它基于 结构实现,默认是一个最大堆(队首元素始终是最大的元素)。

1. 最大堆(默认)

priority_queue<int> pq; // 最大的元素在堆顶

priority_queue<int, vector<int>, less<int>> pq; // 等价写法

2. 最小堆

复制代码
priority_queue<int, vector<int>, greater<int>> pq;  // 最小的元素在堆顶

3. 自定义类型

复制代码
// 方法一:重载 < 运算符
struct Node {
    int val, priority;
    bool operator<(const Node& other) const {
        return priority < other.priority;  // 注意:这里定义的是"小于"关系
    }
};
priority_queue<Node> pq;

// 方法二:自定义比较函数对象
struct Compare {
    bool operator()(const Node& a, const Node& b) {
        return a.priority > b.priority;  // 最小堆
    }
};
priority_queue<Node, vector<Node>, Compare> pq;
复制代码
class Solution {
public:
    struct node{
        int val;
        ListNode* ptr;
        bool operator < (const node &t) const{
            return val > t.val;//实现最小堆
        }
    };
    priority_queue<node> q;

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        for(auto n:lists){
            if(n) q.push({n->val,n});//把每个头先压进队列
        }

        ListNode head,*tail=&head;
        while(!q.empty()){
            auto f=q.top(); 
            q.pop();
            tail->next=f.ptr;
            tail=tail->next;
            if(f.ptr->next) q.push({f.ptr->next->val,f.ptr->next});
        }
        return head.next;
    }
};

两两合并

复制代码
class Solution {
public:
    ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b;
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                tail->next = bPtr; bPtr = bPtr->next;
            }
            tail = tail->next;
        }
        tail->next = (aPtr ? aPtr : bPtr);
        return head.next;
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *ans = nullptr;
        for (size_t i = 0; i < lists.size(); ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }
};

分治法(两两归并):

复制代码
mergeKLists (入口)
    └── merge (分治函数)
            ├── 递归分割左半部分
            ├── 递归分割右半部分
            └── mergeTwoLists (合并两个有序链表)
复制代码
ListNode* merge(vector<ListNode*> &lists, int l, int r) {
    if (l == r) return lists[l];  // 只有一个链表,直接返回
    if (l > r) return nullptr;    // 区间无效,返回空
    
    int mid = (l + r) >> 1;       // 取中点(等价于 (l+r)/2)
    
    // 递归合并左右两部分
    return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
}

递归过程

  • 分割 :将区间 [l, r] 分成 [l, mid][mid+1, r]

  • 递归:分别对左右区间执行相同的分割

  • 合并:将左右两个有序链表合并

  • 假设有 4 个链表:[L1, L2, L3, L4]

复制代码
                    merge(0,3)
                    /        \
              merge(0,1)     merge(2,3)
              /      \        /      \
          merge(0,0) merge(1,1) merge(2,2) merge(3,3)
             L1        L2        L3        L4
              \        /         \        /
              mergeTwoLists      mergeTwoLists
                 (L1,L2)            (L3,L4)
                    \                 /
                    mergeTwoLists((L1,L2), (L3,L4))
                              |
                           最终结果
  • 具体合并顺序

  • 递归到底:得到 L1, L2, L3, L4

  • 第一次合并:mergeTwoLists(L1, L2)L12

  • 第一次合并:mergeTwoLists(L3, L4)L34

  • 最终合并:mergeTwoLists(L12, L34) → 结果

    复制代码
    class Solution {
    public:
        ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
            if ((!a) || (!b)) return a ? a : b;
            ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
            while (aPtr && bPtr) {
                if (aPtr->val < bPtr->val) {
                    tail->next = aPtr; aPtr = aPtr->next;
                } else {
                    tail->next = bPtr; bPtr = bPtr->next;
                }
                tail = tail->next;
            }
            tail->next = (aPtr ? aPtr : bPtr);
            return head.next;
        }
    
        ListNode* merge(vector <ListNode*> &lists, int l, int r) {
            if (l == r) return lists[l];
            if (l > r) return nullptr;
            int mid = (l + r) >> 1;
            return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
        }
    
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            return merge(lists, 0, lists.size() - 1);
        }
    }
相关推荐
罗西的思考12 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队15 小时前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC1 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC1 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK1 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
_清歌2 天前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法
统计实现局2 天前
SVD 的三步走:双对角化、Givens 收敛、排序
算法
躬行见万象2 天前
《VLA 系列》UniLab 强化训练 | G1 机器人 |复现
算法
统计实现局2 天前
对称不定分解(Bunch-Kaufman):为什么 Cholesky 不够用
算法