返回

删除链表的倒数第 N 个结点——实战技巧让你轻松应对

后端

征服 LeetCode 第 19 题:巧用指针,删除链表倒数第 N 个结点

简介

对于程序员而言,算法题是必不可少的训练场,它能检验你的编程能力并促进你的成长。今天,我们就来挑战 LeetCode 第 19 题:删除链表的倒数第 N 个结点。这是一道中等难度的题目,非常适合初学者练习。

题目

给你一个链表,删除链表的倒数第 N 个结点,并返回链表的头结点。

解题思路

解题方法有多种,但这里介绍两种最常见的策略:

双指针法

双指针法是一个巧妙的技巧,它使用两个指针来遍历链表。我们设置一个指针指向链表的头部,另一个指针指向链表的尾部。这两个指针同时向前移动,直到尾指针到达链表的倒数第 N 个结点。此时,头指针恰好指向链表的倒数第 N+1 个结点,我们可以安全地删除它。

代码实现

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummy = new ListNode(0, head);
    ListNode first = dummy;
    ListNode second = dummy;
    for (int i = 0; i < n; i++) {
        second = second.next;
    }
    while (second.next != null) {
        first = first.next;
        second = second.next;
    }
    first.next = first.next.next;
    return dummy.next;
}

快慢指针法

快慢指针法与双指针法类似,但它使用了一个快指针和一个慢指针。快指针每次移动两个结点,而慢指针每次移动一个结点。当快指针到达链表末尾时,慢指针恰好指向链表的倒数第 N 个结点。

代码实现

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode fast = head;
    ListNode slow = head;
    for (int i = 0; i < n; i++) {
        fast = fast.next;
    }
    if (fast == null) {
        return head.next;
    }
    while (fast.next != null) {
        fast = fast.next;
        slow = slow.next;
    }
    slow.next = slow.next.next;
    return head;
}

结论

掌握了解决 LeetCode 第 19 题的方法后,你就能轻松应对类似的链表问题。算法题是提升编程技能的必经之路,每天坚持练习,相信你的编码思维会突飞猛进。

常见问题解答

1. 什么是倒数第 N 个结点?

倒数第 N 个结点是指从链表尾部开始数起的第 N 个结点。

2. 双指针法和快慢指针法有什么区别?

双指针法使用两个指针同时向前移动,而快慢指针法使用一个指针每次移动两个结点,另一个指针每次移动一个结点。

3. 为什么在双指针法中需要一个虚拟头结点?

虚拟头结点可以简化代码逻辑,避免特殊情况的处理。

4. 快慢指针法中,快指针如何跳过 N 个结点?

快指针每次移动两个结点,因此它可以在 n 步内跳过 n 个结点。

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

如果链表长度小于 N,则需要特殊处理,如返回 null 或抛出异常。