返回

巧用「递归 + 双指针」,斩获 LeetCode「删除排序链表中的重复元素 II」难题

IOS

在 LeetCode 中,「删除排序链表中的重复元素 II」问题要求我们删除链表中重复出现的元素,并保留其第一次出现的节点。相较于「删除排序链表中的重复元素」问题,本题的难点在于需要删除所有重复出现的元素

为了应对这个挑战,本文将介绍一种巧妙的「递归 + 双指针」方法。这种方法通过递归和双指针技术,以优雅的方式解决问题,展现其高效性。

算法详解

「递归 + 双指针」方法

该方法包含以下关键步骤:

  1. 创建两个指针:

    • current 指针指向当前节点。
    • prev 指针指向 current 的前一个节点。
  2. 递归处理余下链表:

    • 使用递归调用 removeDuplicates() 函数处理当前节点之后的链表。
  3. 比较当前元素和下一个元素:

    • 如果 current.val 等于 current.next.val,则存在重复。
  4. 删除重复元素:

    • 如果存在重复,则将 prev.next 指向 current.next.next,从而跳过重复元素。
  5. 移动指针:

    • 如果不存在重复,则将 prevcurrent 指针向后移动一位。
  6. 递归返回:

    • 递归返回 prev.next,表示删除重复元素后的链表。

代码实现

def removeDuplicates(head):
    if not head or not head.next:
        return head

    prev = None
    current = head

    while current:
        if current.val == prev.val:
            prev.next = current.next
        else:
            prev = current
        current = current.next

    return head

实例演示

考虑如下链表:

1 -> 2 -> 3 -> 3 -> 4 -> 4 -> 5

使用上述算法,我们可以逐步删除重复元素:

  1. 首先,我们比较 12,发现它们不重复,所以移动指针。
  2. 接下来,比较 23,发现它们重复,所以跳过 3
  3. 继续比较 24,发现它们重复,所以再次跳过 4
  4. 最后,比较 25,发现它们不重复,所以移动指针。

最终,我们得到的结果链表:

1 -> 2 -> 5

优点

  • 高效:通过递归和双指针技术,该方法在时间复杂度上达到 O(n),其中 n 为链表的长度。
  • 易于理解:算法逻辑清晰简单,易于理解和实现。
  • 适用于各种场景:该方法适用于删除任何类型有序链表中的重复元素,不仅限于整数链表。

总结

「递归 + 双指针」方法巧妙地解决了 LeetCode「删除排序链表中的重复元素 II」难题。通过递归处理链表,并使用双指针跳过重复元素,该方法高效且易于理解。这种方法展示了算法思维的精髓,并为解决其他类似问题提供了宝贵的参考。