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);
        }
    }
相关推荐
wayz115 分钟前
Day 11 编程实战:XGBoost金融预测与调参
算法·机器学习·金融·集成学习·boosting
念越7 分钟前
算法每日一题 Day07|双指针求解和为S的两个数
算法·力扣
qeen8714 分钟前
【算法笔记】双指针及其经典例题解析
c++·笔记·算法·双指针
黎阳之光16 分钟前
黎阳之光:以视频孪生+全域感知,助力低空经济破局突围
大数据·人工智能·算法·安全·数字孪生
CM莫问1 小时前
详解机器学习中的马尔可夫链
人工智能·算法·机器学习·概率论·马尔可夫·马尔科夫
南宫萧幕1 小时前
基于 Luenberger 观测器的 PMSM 无速度传感器 id=0 矢量控制系统 Simulink 建模与实现(一)
算法·matlab·汽车·控制
斯维赤1 小时前
每天学习一个小算法:选择排序
java·学习·算法
超级码力6661 小时前
【Latex第三方文档类standalone】standalone类介绍及应用
算法·数学建模·信息可视化
明朝百晓生1 小时前
强化学习 [chapter10] [page3 ]Actor-Critic Methods
算法
peterfei1 小时前
一个 Tauri + Rust AI 编辑器是怎么同时适配 5 家 AI 大厂的?IfAI v0.4.3 架构拆解
人工智能·算法·架构