返回

聪明学霸拆解链表巧妙删除术,快慢指针闪耀全场

前端

巧妙解决删除链表倒数第 n 个节点的难题

概览

当你面对遍历链表的问题时,通常只能从链表头部开始,逐个遍历每个节点。然而,如果你需要删除链表中倒数第 n 个节点,就需要采取巧妙的方法来解决这个问题。本文将深入探讨两种有效的方法:快慢指针和多指针法,并提供代码示例和常见问题解答。

快慢指针法

快慢指针法是一种经典的链表遍历方法,利用两个指针——快指针和慢指针——以不同速度遍历链表。快指针先走 n 步,然后快慢指针同时遍历链表。当快指针到达链表末尾时,慢指针恰好指向倒数第 n 个节点。

def remove_nth_from_end(head, n):
    """
    删除链表中倒数第 n 个节点。

    Args:
        head: 链表的头节点。
        n: 要删除的节点的位置。

    Returns:
        链表的头节点。
    """
    # 创建快慢指针。
    fast = head
    slow = head

    # 快指针先走 n 步。
    for _ in range(n):
        fast = fast.next

    # 当快指针到达链表的末尾时,慢指针就指向了倒数第 n 个节点。
    while fast is not None:
        fast = fast.next
        slow = slow.next

    # 删除倒数第 n 个节点。
    slow.next = slow.next.next

    # 返回链表的头节点。
    return head

多指针法

多指针法是另一种有效的链表遍历方法,使用多个指针同时遍历链表。在这个场景中,可以使用两个指针,一个指向倒数第 n 个节点,另一个指向倒数第 n+1 个节点。当倒数第 n+1 个节点到达链表末尾时,倒数第 n 个节点就指向了倒数第 n 个节点。

def remove_nth_from_end(head, n):
    """
    删除链表中倒数第 n 个节点。

    Args:
        head: 链表的头节点。
        n: 要删除的节点的位置。

    Returns:
        链表的头节点。
    """
    # 创建两个指针,一个指向倒数第 n 个节点,另一个指向倒数第 n+1 个节点。
    p = head
    q = head

    # 倒数第 n 个节点走 n 步。
    for _ in range(n):
        q = q.next

    # 当倒数第 n+1 个节点到达链表的末尾时,倒数第 n 个节点就指向了倒数第 n 个节点。
    while q is not None:
        p = p.next
        q = q.next

    # 删除倒数第 n 个节点。
    p.next = p.next.next

    # 返回链表的头节点。
    return head

结论

无论采用快慢指针法还是多指针法,都可以高效地删除链表中倒数第 n 个节点。这两种方法都很实用,在不同的场景下都可以选择合适的方法来解决问题。

常见问题解答

  1. 为什么需要删除链表中的倒数第 n 个节点?

在实际应用中,可能有各种原因需要删除链表中的倒数第 n 个节点。例如,在实现缓存系统时,需要删除最不经常使用的节点(链表的倒数第 n 个节点),以释放内存空间。

  1. 这两种方法有什么优缺点?

快慢指针法比较简单易懂,实现也相对简单。而多指针法虽然代码稍复杂,但它可以同时遍历链表中的多个位置,在某些场景下效率更高。

  1. 如果链表的长度小于 n,应该如何处理?

如果链表的长度小于 n,则倒数第 n 个节点不存在。在这种情况下,通常会返回原始链表。

  1. 是否可以一次删除链表中多个倒数第 n 个节点?

可以,但需要修改算法以一次删除多个节点。一种方法是使用多重指针,每个指针指向不同的倒数第 n 个节点。

  1. 这两种方法是否适用于循环链表?

快慢指针法适用于循环链表,而多指针法不适用于循环链表,因为循环链表中不存在倒数第 n 个节点。