[面试精选] 0023. 合并 K 个升序链表

1. 题目链接


23. 合并 K 个升序链表 - 力扣(LeetCode)

2. 题目描述


给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

3. 题目示例


示例 1 :

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2 :

输入:lists = []
输出:[]

4. 解题思路


  1. 问题分解
    • 将合并K个链表的问题分解为多个合并两个链表的问题
    • 采用分治策略,递归地将链表数组分成两半
  2. 关键步骤
    • 分治框架
      1. 基本情况:当范围为空返回null,单个链表直接返回
      2. 递归处理左右两半
      3. 合并左右结果
    • 合并操作:使用经典的合并两个有序链表算法
  3. 优化点
    • 避免顺序合并导致的重复遍历(如1+2,然后(1+2)+3…)
    • 分治策略使合并过程更平衡,减少重复工作

5. 题解代码


class Solution {
    // 主方法:合并K个有序链表
    public ListNode mergeKLists(ListNode[] lists) {
        // 调用分治方法,初始范围是整个数组
        return mergeKLists(lists, 0, lists.length);
    }

    // 分治方法:合并lists[i]到lists[j-1]的链表
    private ListNode mergeKLists(ListNode[] lists, int i, int j) {
        int m = j - i;  // 计算当前范围内链表数量
        
        // 基本情况处理
        if (m == 0) {   // 空数组情况
            return null;
        }
        if (m == 1) {   // 只有一个链表,直接返回
            return lists[i];
        }
        
        // 分治递归
        ListNode left = mergeKLists(lists, i, i + m / 2);  // 合并左半部分
        ListNode right = mergeKLists(lists, i + m / 2, j); // 合并右半部分
        
        // 合并左右两部分结果
        return mergeTwoLists(left, right);
    }

    // 辅助方法:合并两个有序链表(21题解法)
    private ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dummy = new ListNode();  // 哨兵节点
        ListNode cur = dummy;             // 当前合并位置
        
        // 双指针遍历
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                cur.next = list1;
                list1 = list1.next;
            } else {
                cur.next = list2;
                list2 = list2.next;
            }
            cur = cur.next;
        }
        
        // 处理剩余节点
        cur.next = (list1 != null) ? list1 : list2;
        return dummy.next;
    }
}


6. 复杂度分析


  1. 时间复杂度:O(NlogK)
    • 每次合并操作时间复杂度为O(N),其中N是总节点数
    • 分治树高度为logK(K是链表数量)
    • 综合:O(NlogK)
  2. 空间复杂度:O(logK)
    • 递归调用栈深度为logK
    • 合并操作使用常数空间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值