【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;
    }
}
相关推荐
Aphelios3809 分钟前
一次锁内网络IO引发的Tomcat线程池“饿死”事故
java·开发语言·spring boot·elasticsearch·tomcat·网络io阻塞·线程池耗尽
不可求~29 分钟前
C++ std::string_view 不是字符串:从悬空引用到安全用法
java·开发语言·c++
Lam Tang30 分钟前
APS 系列文章10
java·代理模式
en.en..1 小时前
数据结构考点解析:逻辑闭环与存储循环辨析
数据结构
考虑考虑1 小时前
Excel导入时产生特殊字符处理
java·后端·java ee
Scabbards_2 小时前
面试Leetcode - Heap 堆
java·leetcode·面试
程序员清风2 小时前
专业再升级!程序员专属显示器明基RD280UG上手实测!
java·后端·面试
布莱克6053 小时前
数据库索引分类:数据结构、物理存储与逻辑角度详解
数据结构·数据库
Lam Tang4 小时前
APS 系列文章 08
java·代理模式
Fa_Mian_Tuan4 小时前
图论基础|邻接矩阵超详细讲解(含无向/有向/带权图+完整可运行C语言代码)
c语言·数据结构·笔记·算法·图论