返回

征服 LeetCode 23:合并 K 个升序链表

前端

合并 K 个升序链表:终极指南

在计算机科学的领域中,数据结构是用于高效存储和管理数据的基本构建块。链表是一种广泛使用的动态数据结构,以其灵活性、易于插入和删除而著称。合并多个升序链表是一个经典算法问题,让我们踏上征服它的旅程。

问题陈述

LeetCode 23 要求我们合并一个包含 K 个升序链表的数组。我们的目标是创建新的单链表,其中包含所有原始链表中的元素,并按升序排列。

理解算法

合并升序链表有多种方法。让我们探索两种最常用的技术:

1. 递归分治

递归分治法遵循“分而治之”的原则。我们将其分解成较小的子问题,然后递归地解决这些子问题。

算法步骤:

  • 基础情况: 如果链表数组为空或只有一个链表,则直接返回该链表。
  • 分治: 将链表数组分成两半。对每一半递归调用合并函数,得到两个合并后的链表。
  • 合并: 将两个合并后的链表合并在一起。

2. 优先队列

优先队列是一种数据结构,始终维护一个有序列表。我们可以使用最小优先队列,其中包含链表头节点的引用。

算法步骤:

  • 初始化: 将所有链表头节点添加到优先队列。
  • 循环: 只要优先队列不为空,请执行以下步骤:
    • 从优先队列中删除最小值(即具有最小值的链表头节点)。
    • 将最小值添加到合并后的链表中。
    • 如果最小值指向的链表还有下一个节点,则将其添加到优先队列中。

代码示例

Python 递归解法

def merge_k_sorted_lists(lists):
    if not lists:
        return None

    if len(lists) == 1:
        return lists[0]

    mid = len(lists) // 2
    left_half = merge_k_sorted_lists(lists[:mid])
    right_half = merge_k_sorted_lists(lists[mid:])

    return merge_two_sorted_lists(left_half, right_half)


def merge_two_sorted_lists(list1, list2):
    if not list1:
        return list2
    if not list2:
        return list1

    if list1.val < list2.val:
        list1.next = merge_two_sorted_lists(list1.next, list2)
        return list1
    else:
        list2.next = merge_two_sorted_lists(list1, list2.next)
        return list2

Python 优先队列解法

from queue import PriorityQueue

def merge_k_sorted_lists(lists):
    if not lists:
        return None

    q = PriorityQueue()

    for head in lists:
        if head:
            q.put((head.val, head))

    dummy = ListNode(-1)
    current = dummy

    while not q.empty():
        _, head = q.get()
        current.next = head
        current = current.next
        if head.next:
            q.put((head.next.val, head.next))

    return dummy.next

常见问题解答

  1. 为什么需要合并链表?

    • 合并链表用于将多个来源的数据组合成一个有序的集合。它在合并排序算法和构建分层数据结构等应用程序中非常有用。
  2. 递归和优先队列哪种方法更好?

    • 对于较小的链表数组,递归方法可能更简洁、高效。然而,对于较大的数组,优先队列方法通常具有更好的性能。
  3. 链表数组可以包含重复元素吗?

    • 是的,链表数组可以包含重复元素。算法将保持所有重复元素的顺序。
  4. 算法的时间复杂度是多少?

    • 对于递归方法,时间复杂度为 O(N log K),其中 N 是所有链表中的节点总数,K 是链表数组的长度。对于优先队列方法,时间复杂度为 O(N log N)。
  5. 如何将算法扩展到处理无序链表?

    • 我们可以首先使用归并排序或快速排序等算法将每个链表排序。然后,我们可以应用前面讨论的合并有序链表技术。

结论

合并 K 个升序链表是一个有用的算法问题,在各种计算机科学应用程序中都有应用。通过理解递归和优先队列等技术,我们可以轻松解决此问题并有效地管理数据。