返回

LeetCode: 21. 合并两个有序链表——有效解决方案,难题不再难!

见解分享

合并两个有序链表:双指针法指南

简介

在 LeetCode 21 题中,我们的目标是合并两个升序链表,创建一个新的升序链表。为了有效地解决这个问题,我们可以采用双指针法,它以其简洁性和效率而著称。

双指针法

双指针法使用两个指针,一个指针指向每个链表的表头。通过比较两个指针当前指向的节点的值,我们确定较小的值,然后将该节点添加到新链表中。随后,我们将指向较小值节点的指针移动到下一个节点。

这个过程重复进行,直到两个链表都为空。此时,我们将任何剩余节点添加到新链表中,然后返回其头节点。

步骤分解

以下是双指针法的逐步分解:

  1. 初始化双指针: 创建一个新的链表,并初始化指向两个给定链表头节点的指针。
  2. 比较节点值: 比较两个指针当前指向的节点值。
  3. 添加较小节点: 将较小值节点添加到新链表中。
  4. 移动较小指针: 将指向较小值节点的指针移动到下一个节点。
  5. 检查空链表: 如果一个链表为空,则将另一个链表的剩余节点添加到新链表中。
  6. 返回新链表: 最后,返回新链表的头节点。

代码示例

def merge_two_lists(l1, l2):
    """
    合并两个有序链表,并返回合并后的链表。

    参数:
    l1 (ListNode): 第一个链表的头节点。
    l2 (ListNode): 第二个链表的头节点。

    返回:
    ListNode: 合并后的链表的头节点。
    """

    # 创建一个新的链表,作为合并后的链表。
    head = ListNode(0)

    # 初始化双指针。
    ptr1 = l1
    ptr2 = l2

    # 遍历两个链表,并将较小的节点添加到新的链表中。
    while ptr1 and ptr2:
        if ptr1.val < ptr2.val:
            head.next = ptr1
            ptr1 = ptr1.next
        else:
            head.next = ptr2
            ptr2 = ptr2.next

        head = head.next

    # 将剩余的节点添加到新的链表中。
    if ptr1:
        head.next = ptr1
    if ptr2:
        head.next = ptr2

    # 返回合并后的链表的头节点。
    return head.next

扩展思考

除了双指针法,还有其他方法可以合并两个有序链表,包括:

  • 迭代法: 使用循环迭代两个链表,并比较每个节点的值。
  • 递归法: 将问题分解为两个子问题,合并两个链表的前半部分和合并两个链表的后半部分。

结论

双指针法是合并两个有序链表的高效方法。它易于实现,并且具有时间复杂度为 O(n),其中 n 是两个链表中节点的总数。通过理解双指针法的步骤和代码示例,您可以自信地解决 LeetCode 21 题。

常见问题解答

  1. 双指针法的复杂度是多少?
    答:O(n)

  2. 双指针法比其他方法有什么优势?
    答:易于实现且效率高。

  3. 可以使用递归法合并链表吗?
    答:是的,可以。

  4. 双指针法可以在合并其他数据结构时使用吗?
    答:是的,它可以用于合并其他线性数据结构,例如数组或栈。

  5. 如何解决链表中存在循环引用问题?
    答:使用哈希表来跟踪已访问的节点,或者使用两个指针来检测循环。