LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)

LeetCode 23. 合并 K 个升序链表 ------ 小顶堆(PriorityQueue)

📌 题目链接


💡 解题思路

本题是 21. 合并两个有序链表 的进阶版。

暴力思路(不推荐)

  • 两两合并:O(kN)
  • 效率低,容易超时
java 复制代码
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0) {
            return null;
        }
        if(lists.length == 1) {
            return lists[0];
        }
        ListNode res = new ListNode();
        res = merge(lists[0], lists[1]);
        for(int i=2;i<lists.length;i++) {
            res = merge(res, lists[i]);
        }
        return res;
    }
    public ListNode merge(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode();
        ListNode cur = dummy;
        while(l1!=null && l2!=null) {
            if(l1.val < l2.val) {
                cur.next = l1;
                l1=l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = l1!=null ? l1 : l2;
        return dummy.next;
    }
}

最优思路:小顶堆(优先队列)

核心思想:

每次只取 当前所有链表头部最小的节点

具体做法:

  1. 将所有链表的头结点加入 小顶堆
  2. 每次从堆中取出最小节点,接到结果链表
  3. 若该节点还有后继节点,将其加入堆
  4. 重复直到堆为空

🛠 关键技术点

1️⃣ 使用 PriorityQueue 构建小顶堆

java 复制代码
PriorityQueue<ListNode> pq =
    new PriorityQueue<>((a, b) -> a.val - b.val);
  • Java 默认是最小堆
  • val 从小到大排序

2️⃣ 初始化堆

java 复制代码
for (ListNode node : lists) {
    if (node != null) {
        pq.offer(node);
    }
}
  • 只放非空链表
  • 堆中最多同时存在 k 个节点

3️⃣ 动态维护堆

java 复制代码
ListNode node = pq.poll();
if (node.next != null) {
    pq.offer(node.next);
}

📌 关键点:

  • 每取出一个节点,就补一个它的后继节点进堆
  • 保证堆中始终是各链表当前的"最小值候选"

🧩 完整代码(Java)

java 复制代码
/**
 * Definition for singly-linked list.
 */
public class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        // 1. 最小堆(按节点值排序)
        PriorityQueue<ListNode> pq =
            new PriorityQueue<>((a, b) -> a.val - b.val);

        // 2. 所有链表的头结点入堆
        for (ListNode node : lists) {
            if (node != null) {
                pq.offer(node);
            }
        }

        // 3. 构造结果链表
        ListNode dummy = new ListNode();
        ListNode cur = dummy;

        while (!pq.isEmpty()) {
            ListNode node = pq.poll();
            if (node.next != null) {
                pq.offer(node.next);
            }
            cur.next = node;
            cur = cur.next;
        }

        return dummy.next;
    }
}

⏱ 复杂度分析

指标 复杂度 说明
时间复杂度 O(N log k) N 为总节点数,k 为链表个数
空间复杂度 O(k) 堆中最多存放 k 个节点

✅ 总结

  • ✅ 最小堆写法 逻辑最清晰、最好写
  • ✅ 面试中极其常见,属于必会题
  • ⚠️ 若要求 O(1) 空间 ,可使用 分治法(类似归并排序)

一句话总结:

K 路归并,堆中永远只保留"下一个可能的最小值"。

相关推荐
csdn_aspnet19 分钟前
C# 第k个最小元素(K’th Smallest Element)
算法·c#·排序算法
BioRunYiXue23 分钟前
RACE技术全攻略:从全长克隆到靶基因验证
java·javascript·网络·人工智能·科技·算法·eclipse
ZPC82101 小时前
joy 及sensor_msgs
算法
Three_ST1 小时前
沐神-动手学习深度学习-习题答案4.4模型选择,欠拟合,过拟合
人工智能·python·深度学习·学习·算法
CIO_Alliance1 小时前
AI深度系列(2)| CNN卷积池化感受野原理:从局部感知到全局视野
人工智能·深度学习·线性代数·算法·计算机视觉·企业ai转型·企业cio联盟
探物 AI1 小时前
机器人清理墙角蜘蛛网,背后需要哪些算法?——从视觉分割到贴墙力控
算法·机器人
青 春 记 忆1 小时前
LeetCode 226. 翻转二叉树|Python 解法详解
python·算法·leetcode
民乐团扒谱机2 小时前
【微科普】压缩感知(CS):违反了奈奎斯特采样定理?不先采集也能还原信号?大白话讲透稀疏采样、L1重建与OMP,一文吃透附代码
python·神经网络·线性代数·算法·数学建模·压缩感知·奈奎斯特
88号技师2 小时前
2026年SCI-分数牛顿衍生优化算法Fractional Newton-derived optimizer-附Matlab免费代码
开发语言·算法·数学建模·matlab·优化算法
夏玉林的学习之路2 小时前
算法7.链式栈
算法