返回

轻松掌握!链表中倒数第 N 个节点的删除技巧

前端

删除链表中的倒数第 N 个节点:双指针法详解

什么是双指针法?

双指针法是一种链表算法技术,它利用两个或更多指针同时遍历链表,以高效地解决各种链表问题。在删除倒数第 N 个节点的场景中,我们使用两个指针:

  • 慢指针(slow): 从链表头结点开始,每次移动一步。
  • 快指针(fast): 也从链表头结点开始,但先移动 N 步,然后再与慢指针一起移动。

如何删除倒数第 N 个节点?

删除链表中的倒数第 N 个节点涉及以下步骤:

  1. 移动快指针 N 步: 将快指针向前移动 N 步,到达链表的第 N+1 个节点。
  2. 同时移动慢指针和快指针: 当快指针到达链表尾部时,慢指针指向的就是倒数第 N 个节点的前一个节点。
  3. 删除目标节点: 将慢指针指向的目标节点的前一个节点的 next 指针指向目标节点的 next 指针,即可删除目标节点。

代码示例

Python:

def remove_nth_from_end(head, n):
    slow = head
    fast = head
    
    # 移动快指针 N 步
    for _ in range(n):
        fast = fast.next

    # 如果快指针已经到达链表尾部,则删除头结点
    if not fast:
        return head.next

    # 同时移动慢指针和快指针,直到快指针到达链表尾部
    while fast.next:
        slow = slow.next
        fast = fast.next

    # 删除目标节点
    slow.next = slow.next.next

    return head

Java:

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode slow = head;
    ListNode fast = head;

    // 移动快指针 N 步
    for (int i = 0; i < n; i++) {
        fast = fast.next;
    }

    // 如果快指针已经到达链表尾部,则删除头结点
    if (fast == null) {
        return head.next;
    }

    // 同时移动慢指针和快指针,直到快指针到达链表尾部
    while (fast.next != null) {
        slow = slow.next;
        fast = fast.next;
    }

    // 删除目标节点
    slow.next = slow.next.next;

    return head;
}

C++:

ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode* slow = head;
    ListNode* fast = head;

    // 移动快指针 N 步
    for (int i = 0; i < n; i++) {
        fast = fast->next;
    }

    // 如果快指针已经到达链表尾部,则删除头结点
    if (fast == nullptr) {
        return head->next;
    }

    // 同时移动慢指针和快指针,直到快指针到达链表尾部
    while (fast->next != nullptr) {
        slow = slow->next;
        fast = fast->next;
    }

    // 删除目标节点
    slow->next = slow->next->next;

    return head;
}

应用场景

双指针法不仅仅用于删除链表中的倒数第 N 个节点,它在以下场景中也有广泛的应用:

  • 删除链表中的重复元素
  • 寻找链表的中间节点
  • 反转链表

总结

双指针法是一种高效且通用的链表算法,它可以解决多种与链表相关的操作问题。理解和掌握双指针法可以极大地提升你的链表编程能力。

常见问题解答

  1. 为什么双指针法效率高?

双指针法通过并行遍历链表,可以避免多次遍历链表的开销,从而提高了算法的效率。

  1. 双指针法只能用于删除倒数第 N 个节点吗?

不,双指针法还可以用于其他链表操作,如删除重复元素、寻找中间节点、反转链表等。

  1. 如何处理链表长度小于 N 的情况?

如果链表长度小于 N,则直接删除头结点即可。

  1. 如何处理链表为空的情况?

如果链表为空,则直接返回 null

  1. 双指针法是否可以在其他数据结构中使用?

双指针法不仅可以用于链表,还可以应用于数组、字符串等其他数据结构。