C#删除一个单向链表的倒数第n个节点
要删除一个单向链表的倒数第n个节点,可以使用双指针(快慢指针)的方法来高效实现。以下是详细的思路和步骤,以及C#代码实现。
思路详解
-
问题分析:单向链表只能从头节点开始遍历,无法直接访问倒数第n个节点。因此,需要找到一种方式来确定倒数第n个节点的位置。
-
双指针法:使用两个指针(快指针和慢指针),通过让快指针先移动n步,然后同时移动快慢指针,当快指针到达链表末尾时,慢指针恰好指向倒数第n个节点的前一个节点(这样便于删除操作)。
-
哑节点(Dummy Node):引入一个哑节点作为头节点的前驱节点,可以简化删除头节点的特殊情况(例如,当n等于链表长度时,需要删除头节点)。
-
步骤:
-
创建哑节点,并将其next指向头节点。
-
初始化快指针和慢指针,都指向哑节点。
-
快指针先移动n步。
-
然后同时移动快慢指针,直到快指针到达最后一个节点(即快指针的next为null)。
-
此时慢指针指向倒数第n个节点的前一个节点,将慢指针的next指向慢指针的next的next,从而删除倒数第n个节点。
-
返回哑节点的next作为新链表的头。
-
-
边界情况:假设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),只使用了常数级别的额外空间。

浙公网安备 33010602011771号