【LeetCode 热题100】 23. 合并 K 个升序链表的算法思路及python代码

23. 合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 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 = []
输出:[]

示例 3:

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

算法思路

该问题采用分治法(Divide and Conquer)来合并K个有序链表。核心思想是将大问题分解为小问题,递归合并相邻的链表,最终合并成一个完整的链表。具体步骤如下:

  • 分解: 将链表数组递归地分成两半,直到每个子问题仅包含一个链表。
  • 合并: 将相邻的两个子问题(链表)合并,利用合并两个有序链表的算法逐步向上归并。
  • 终止条件: 当子问题的区间为空时返回None,当区间仅包含一个链表时直接返回该链表。

步骤详解

  1. 合并两个链表mergeTwoLists):
    • 使用双指针遍历两个链表,逐个比较节点值,按升序连接。
    • 当一个链表遍历完成后,将剩余部分直接连接到合并链表的末尾。
  2. 分治合并merge):
    • 递归拆分:将当前链表数组区间分成左右两部分,分别递归合并左右部分。
    • 合并结果:将左右两部分合并后的结果再次合并,最终返回完整链表。
  3. 主函数mergeKLists):调用分治合并函数,处理初始链表数组。

关键点

  • 分治策略: 通过递归将K个链表逐层拆分,减少合并次数,降低时间复杂度。
  • 合并两个链表: 高效的合并方法是整个算法的基石,确保每一步合并操作的时间复杂度为线性。
  • 递归终止条件: 正确处理空链表和单链表的情况,避免无效递归。

复杂度分析

  • 时间复杂度: O ( N l o g K ) O(N log K) O(NlogK),其中 N N N为所有链表的总节点数, K K K为链表个数。每次分治合并需要 O ( N ) O(N) O(N)时间,分治层数为 l o g K log K logK层。
  • 空间复杂度: O ( l o g K ) O(log K) O(logK),递归调用栈的深度为 l o g K log K logK层,每层需要常数空间。

代码实现

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, a: Optional[ListNode], b: Optional[ListNode]) -> Optional[ListNode]:
        if not a or not b:
            return a if a else b
        # 创建虚拟头节点简化操作
        dummy = ListNode()
        tail = dummy
        a_ptr, b_ptr = a, b
        
        while a_ptr and b_ptr:
            if a_ptr.val < b_ptr.val:
                tail.next = a_ptr
                a_ptr = a_ptr.next
            else:
                tail.next = b_ptr
                b_ptr = b_ptr.next
            tail = tail.next
        
        # 连接剩余部分
        tail.next = a_ptr if a_ptr else b_ptr
        return dummy.next

    def merge(self, lists: List[Optional[ListNode]], l: int, r: int) -> Optional[ListNode]:
        if l > r:
            return None
        if l == r:
            return lists[l]
        mid = (l + r) // 2
        left = self.merge(lists, l, mid)
        right = self.merge(lists, mid + 1, r)
        return self.mergeTwoLists(left, right)

    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        return self.merge(lists, 0, len(lists) - 1)

【LeetCode 热题100】 23. 合并 K 个升序链表的算法思路及python代码_第1张图片

你可能感兴趣的:(LeetCode热题100,算法,leetcode,链表)