C#删除一个单向链表的倒数第n个节点

要删除一个单向链表的倒数第n个节点,可以使用双指针(快慢指针)的方法来高效实现。以下是详细的思路和步骤,以及C#代码实现。

思路详解

  1. 问题分析:单向链表只能从头节点开始遍历,无法直接访问倒数第n个节点。因此,需要找到一种方式来确定倒数第n个节点的位置。

  2. 双指针法:使用两个指针(快指针和慢指针),通过让快指针先移动n步,然后同时移动快慢指针,当快指针到达链表末尾时,慢指针恰好指向倒数第n个节点的前一个节点(这样便于删除操作)。

  3. 哑节点(Dummy Node):引入一个哑节点作为头节点的前驱节点,可以简化删除头节点的特殊情况(例如,当n等于链表长度时,需要删除头节点)。

  4. 步骤:

    • 创建哑节点,并将其next指向头节点。

    • 初始化快指针和慢指针,都指向哑节点。

    • 快指针先移动n步。

    • 然后同时移动快慢指针,直到快指针到达最后一个节点(即快指针的next为null)。

    • 此时慢指针指向倒数第n个节点的前一个节点,将慢指针的next指向慢指针的next的next,从而删除倒数第n个节点。

    • 返回哑节点的next作为新链表的头。

  5. 边界情况:假设n是有效的(即1 ≤ n ≤ 链表长度),但代码中最好添加检查,确保快指针在移动n步时不会超出链表范围(如果n无效,可以抛出异常或返回原链表)。

C#代码实现

public class ListNode {
    public int val;
    public ListNode next;
    public ListNode(int val = 0, ListNode next = null) {
        this.val = val;
        this.next = next;
    }
}

public class Solution {
    public ListNode RemoveNthFromEnd(ListNode head, int n) {
        // 创建哑节点,简化头节点删除操作
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode fast = dummy;
        ListNode slow = dummy;
        
        // 快指针先移动n步
        for (int i = 0; i < n; i++) {
            // 如果n无效,fast可能为null,但假设n有效,所以不加检查
            fast = fast.next;
        }
        
        // 同时移动快慢指针,直到快指针到达最后一个节点
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        
        // 删除倒数第n个节点
        slow.next = slow.next.next;
        
        return dummy.next;
    }
}

示例说明

  • 假设链表为 1 -> 2 -> 3 -> 4 -> 5,n = 2。

  • 快指针先移动2步,指向节点2。

  • 然后快慢指针同时移动:快指针移动到节点3、4、5(当快指针指向节点5时,快指针的next为null,停止移动),此时慢指针指向节点3。

  • 删除慢指针的next(节点4),链表变为 1 -> 2 -> 3 -> 5。

这种方法的时间复杂度为O(L),其中L是链表的长度,只需遍历一次链表。空间复杂度为O(1),只使用了常数级别的额外空间。

posted @ 2025-09-03 00:39  龙宝gogogo  阅读(30)  评论(0)    收藏  举报