【LeetCodehot100】T23:合并k个升序链表

T23:合并k个升序链表

题目要求:

k 个已经排好序的链表

例如:

list1: 1 → 4 → 5

list2: 1 → 3 → 4

list3: 2 → 6

要求:

把它们合并成一个新的有序链表

最终结果:

1 → 1 → 2 → 3 → 4 → 4 → 5 → 6

题目核心

如何把多个有序链表合并成一个有序链表?

核心思路(分治 / 归并)

像归并排序一样:

k个链表

分成两半

分别合并

再合并结果

分治函数,合并链表代码实现

分治函数

java 复制代码
private ListNode merge(ListNode[] lists, int left, int right){
    if(left == right){
        return lists[left];
    }

    int mid = (left + right) / 2;

    ListNode l1 = merge(lists, left, mid);
    ListNode l2 = merge(lists, mid + 1, right);

    return mergeTwoLists(l1, l2);
}

逻辑:

递归拆分

直到只剩一个链表

再开始合并

合并两个链表

java 复制代码
private ListNode mergeTwoLists(ListNode l1, ListNode l2){

    ListNode dummy = new ListNode(0);
    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;
    }

    if(l1 != null) cur.next = l1;
    if(l2 != null) cur.next = l2;

    return dummy.next;
}

代码实现

java 复制代码
class Solution {

    // 主函数:合并 k 个有序链表
    public ListNode mergeKLists(ListNode[] lists) {

        // 边界情况:如果数组为空,直接返回 null
        if (lists == null || lists.length == 0) {
            return null;
        }

        // 调用分治函数
        return merge(lists, 0, lists.length - 1);
    }


    // 分治函数:负责把多个链表不断拆分并合并
    private ListNode merge(ListNode[] lists, int left, int right) {

        // 如果只剩一个链表,直接返回
        if (left == right) {
            return lists[left];
        }

        // 计算中间位置
        int mid = (left + right) / 2;

        // 递归合并左半部分
        ListNode l1 = merge(lists, left, mid);

        // 递归合并右半部分
        ListNode l2 = merge(lists, mid + 1, right);

        // 最后把两个已经排好序的链表合并
        return mergeTwoLists(l1, l2);
    }


    // 合并两个有序链表(经典模板)
    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {

        // 创建虚拟头节点(方便操作)
        ListNode dummy = new ListNode(0);

        // cur 指针用于构建新链表
        ListNode cur = dummy;

        // 只要两个链表都没遍历完
        while (l1 != null && l2 != null) {

            // 谁小就接谁
            if (l1.val < l2.val) {

                cur.next = l1;   // 接入 l1 节点
                l1 = l1.next;    // l1 指针后移

            } else {

                cur.next = l2;   // 接入 l2 节点
                l2 = l2.next;    // l2 指针后移

            }

            // cur 指针前进
            cur = cur.next;
        }

        // 如果 l1 还有剩余节点
        if (l1 != null) {
            cur.next = l1;
        }

        // 如果 l2 还有剩余节点
        if (l2 != null) {
            cur.next = l2;
        }

        // 返回合并后的链表头节点
        return dummy.next;
    }
}
相关推荐
二哈赛车手6 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
栗子~~7 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
YDS8297 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— RAG知识库的搭建和接口实现
java·ai·springboot·agent·rag·deepseek
未若君雅裁9 小时前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
AI人工智能+电脑小能手9 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
阿维的博客日记10 小时前
Nacos 为什么能让配置动态生效?(涉及 @RefreshScope 注解)
java·spring
雨辰AI10 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
Mr. zhihao11 小时前
深入解析redis基本数据结构
数据结构·数据库·redis
辰海Coding11 小时前
MiniSpring框架学习-完成的 IoC 容器
java·spring boot·学习·架构
念何架构之路11 小时前
Go语言加密算法
数据结构·算法·哈希算法