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);
        }
    }
相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her14 天前
并查集-听课笔记
笔记·算法·并查集
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven4 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark4 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218614 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法