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);
        }
    }
相关推荐
kobesdu2 小时前
laser_line_extraction线段提取开源功能包解读和使用例程
人工智能·算法·机器人·ros
abant22 小时前
leetcode 105 前序中序构建二叉树
算法·leetcode·职场和发展
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 438. 找到字符串中所有字母异位词 | C++ 滑动窗口题解
c++·算法·leetcode
Mr_Xuhhh2 小时前
深入理解Java数组:从定义到高阶应用
开发语言·python·算法
倦王2 小时前
力扣日刷复习:
算法·leetcode·职场和发展
py有趣2 小时前
力扣热门100题之二叉树的中序遍历
算法·leetcode·职场和发展
DFT计算杂谈2 小时前
eDMFT安装教程
java·服务器·前端·python·算法
我不是懒洋洋2 小时前
【数据结构】单链表专题(详细代码及配图)
c语言·数据结构·c++·算法·visual studio
j_xxx404_2 小时前
蓝桥杯--搜索(DFS基础回溯法,剪枝,记忆化搜索)
数据结构·c++·算法·蓝桥杯·深度优先·图论