删除链表倒数第n个节点需用双指针法:先创建虚拟头节点,快指针先走n步,再与慢指针同步前进至快指针到达尾节点,此时慢指针指向待删节点前驱,修改其next指针即可。

要删除链表倒数第 N 个节点,核心思路是:先让一个指针走 N 步,再让另一个指针从头出发,两个指针同步前进,当前者到达末尾时,后者恰好停在待删除节点的前一个位置。
使用双指针定位前驱节点
关键不是直接找“倒数第 N 个”,而是找它的前一个节点(便于修改 next 指针)。步骤如下:
- 创建虚拟头节点(dummy),指向原链表头,避免单独处理删头节点的情况
- 初始化快慢指针都指向 dummy
- 快指针先向前走 N 步(注意:走完后它指向的是倒数第 N 个节点的前一个?不,是倒数第 N+1 个节点的位置——因为从 dummy 开始走 N 步,刚好跨过 N 个节点)
- 然后快慢指针一起走,直到快指针的 next === null(即快指针到达最后一个节点)
- 此时慢指针的 next 就是要删除的节点,执行 slow->next = slow->next->next
注意边界与健壮性处理
实际编码中需考虑这些情况:
- N 大于链表长度:可提前遍历一次得长度,或让快指针走 N 步时检查是否提前为 null
- N 等于链表长度:即删头节点,虚拟头正好派上用场,删完返回 dummy->next
- 空链表或 N ≤ 0:应直接返回原链表或抛异常,视题目要求而定
PHP 实现示例(含 ListNode 定义)
假设已定义标准单链表节点:
立即学习“PHP免费学习笔记(深入)”;
class ListNode {
public $val = 0;
public $next = null;
function __construct($val = 0, $next = null) {
$this->val = $val;
$this->next = $next;
}
}
删除逻辑函数:
function removeNthFromEnd($head, $n) {
$dummy = new ListNode(0);
$dummy->next = $head;
$fast = $slow = $dummy;
// 快指针先走 n 步
for ($i = 0; $i < $n; $i++) {
if ($fast === null) return $head; // n 超出长度,不作删除
$fast = $fast->next;
}
// 同步移动,直到 fast 到达末尾(fast->next == null)
while ($fast->next !== null) {
$fast = $fast->next;
$slow = $slow->next;
}
$slow->next = $slow->next->next;
return $dummy->next;
}











