返回

剖析LeetCode:巧用双指针法删除链表倒数第N个节点(每日计划)

闲谈

删除链表的倒数第N个节点:巧妙的双指针法

什么是双指针法?

删除链表的倒数第N个节点时,双指针法是一种巧妙且高效的方法。该方法的核心思想是使用两个指针,一个指针(称为“快指针”)先移动N步,然后另一个指针(称为“慢指针”)开始移动。当快指针到达链表尾部时,慢指针刚好位于要删除节点的前一个节点。

双指针法的具体步骤

  1. 初始化两个指针,fast_ptr和slow_ptr,均指向链表头结点。
  2. fast_ptr先移动N步,以确保它始终比slow_ptr领先N步。
  3. 当fast_ptr到达链表尾部时,slow_ptr刚好位于要删除节点的前一个节点。
  4. 删除slow_ptr的下一个节点(即要删除的节点)。
  5. 返回删除后的链表头结点。

一个示例

假设我们有一个链表:[1, 2, 3, 4, 5],并且我们要删除倒数第2个节点。

按照双指针法,我们可以这样操作:

  1. 首先,我们将fast_ptr和slow_ptr都指向链表头结点1。
  2. 然后,fast_ptr先移动2步,到达节点3。
  3. 此时,slow_ptr仍然位于节点1,因为fast_ptr比slow_ptr领先2步。
  4. 当fast_ptr到达链表尾部5时,slow_ptr刚好位于节点3的前一个节点2。
  5. 因此,我们要删除节点3。我们只需要将slow_ptr的下一个节点(即节点3)指向节点3的下一个节点(即节点4)即可。
  6. 删除节点3后,链表变为:[1, 2, 4, 5]。
  7. 最后,我们将删除后的链表头结点1返回。

代码实现

def removeNthFromEnd(head: ListNode, n: int) -> ListNode:
    """
    删除链表的倒数第 n 个节点
    :param head: 链表头结点
    :param n: 要删除的倒数第 n 个节点
    :return: 返回删除后的链表头结点
    """
    # 创建两个指针:快指针和慢指针
    fast_ptr = head
    slow_ptr = head

    # 快指针先移动 n 步
    for _ in range(n):
        if fast_ptr is None:
            return head.next  # 如果快指针到达链表尾部,则删除头节点
        fast_ptr = fast_ptr.next

    # 当快指针到达链表尾部时,慢指针刚好位于要删除节点的前一个节点
    while fast_ptr is not None:
        fast_ptr = fast_ptr.next
        slow_ptr = slow_ptr.next

    # 删除慢指针的下一个节点
    slow_ptr.next = slow_ptr.next.next

    return head

结论

双指针法是一种删除链表的倒数第N个节点的巧妙算法。它通过使用两个指针,确保慢指针始终位于要删除节点的前一个节点,从而实现高效删除。

常见问题解答

  1. 为什么要使用双指针法?
    双指针法通过同时移动两个指针,确保慢指针始终位于要删除节点的前一个节点,从而实现高效删除,而不需要遍历整个链表。
  2. 双指针法是如何工作的?
    快指针先移动N步,然后慢指针开始移动。当快指针到达链表尾部时,慢指针刚好位于要删除节点的前一个节点。
  3. 双指针法的复杂度是多少?
    双指针法的复杂度为O(n),其中n是链表的长度。
  4. 双指针法有哪些其他应用?
    双指针法还可以用于解决其他链表问题,例如查找链表中点、判断链表是否有环等。
  5. 除了双指针法,还有哪些删除链表节点的方法?
    除了双指针法,还可以使用其他方法删除链表节点,例如:
    • 递归法
    • 迭代法
    • 哨兵节点法