返回

LeetCode 83:扫清重复,筑就有序单链表

前端

LeetCode 83:扫清重复,筑就有序单链表

在计算机科学领域,链表是一种常见的数据结构,由一系列按特定顺序排列的节点组成,每个节点包含数据和指向下一个节点的指针。当我们处理有序数据时,链表通常是理想的选择,它可以高效地进行元素的插入、删除和查找操作。

LeetCode 83题正是针对有序单链表的一道经典算法题,题目要求我们删除链表中所有重复的元素,使每个元素只出现一次。乍看之下,这似乎是一项艰巨的任务,但通过精心设计的算法,我们可以巧妙地解决这个问题。

算法详解

为了删除链表中的重复元素,我们需要一个巧妙的策略,可以帮助我们快速识别和跳过重复元素。为此,我们引入三个指针:

  • 当前指针(current):指向当前正在处理的节点。
  • 前驱指针(prev):指向当前指针的前一个节点。
  • 辅助指针(helper):用于遍历链表,帮助我们查找重复元素。

算法的核心思想是,当我们遇到一个重复元素时,我们使用辅助指针找到下一个不重复的元素,然后将当前指针指向该元素,同时将前驱指针指向当前指针,从而跳过重复元素。

具体步骤如下:

  1. 初始化三个指针:当前指针current指向链表的头节点head,前驱指针prev指向空节点,辅助指针helper指向链表的头节点head。
  2. 循环遍历链表,直到当前指针current指向空节点:
    • 如果当前指针current指向的元素与辅助指针helper指向的元素相同,则说明找到了一个重复元素。
    • 将辅助指针helper向前移动一位,继续查找下一个不重复的元素。
    • 将前驱指针prev指向当前指针current,以便跳过重复元素。
  3. 将当前指针current指向辅助指针helper指向的元素,完成一个元素的处理。
  4. 重复步骤2和步骤3,直到辅助指针helper指向空节点。

代码实现

def deleteDuplicates(head):
    """
    :type head: ListNode
    :rtype: ListNode
    """
    # 初始化三个指针
    current = head
    prev = None
    helper = head

    # 循环遍历链表
    while current:
        # 如果找到重复元素
        if helper and current.val == helper.val:
            # 将辅助指针向前移动一位
            helper = helper.next
            # 将前驱指针指向当前指针
            prev = current
            # 将当前指针指向下一个不重复的元素
            current = helper
        # 如果没有找到重复元素
        else:
            # 将前驱指针指向当前指针
            prev = current
            # 将当前指针指向下一个元素
            current = current.next
            # 将辅助指针指向当前指针
            helper = current

    # 返回链表头节点
    return head

复杂度分析

该算法的时间复杂度为O(n),其中n为链表的长度。这是因为辅助指针helper需要遍历整个链表一次,而当前指针current和前驱指针prev最多需要遍历链表两次。因此,算法的总时间复杂度为O(n)。

算法的空间复杂度为O(1),因为我们只需要使用三个指针,它们所占用的空间是常数。

结语

LeetCode 83题是一道经典的算法题,它考验了我们对链表的理解和操作能力。通过精心设计的算法,我们可以巧妙地删除链表中的重复元素,使每个元素只出现一次。希望这篇指南能够帮助您解决LeetCode 83题,并为您的算法学习之旅锦上添花。