图解题库 / 链表 · 快慢指针

19. 删除倒数第 N 个结点

中等 含交互动画

学完这道你应该能: 说清它为什么用「快慢指针」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

删除链表的倒数第 n 个结点,返回头结点。

输入 = 1 → 2 → 3 → 4 → 5, n = 2
输出 = 1 → 2 → 3 → 5 (删掉 4)

思路解析

先遍历数出长度,再从头走 len−n 步找到待删节点的前驱——要走两趟。能不能一趟搞定?让两个指针拉开 n 的固定间距。

fast 先独自走 n 步,于是 fast 比 slow 领先 n 个节点。然后两个一起走,当 fast 到达最后一个节点时,slow 正好落在「倒数第 n 个」的前一个,删它就方便了。

起点 · slow=fast=头:slowfast 都从头出发。

fast 先走 n=2 步:fast 单独走 2 步到 3,slow 还在 1。两者间距 = n = 2,这个间距之后会一直保持。

同步走 · slow→2, fast→4:现在两个一起走一步:slow 到 2,fast 到 4。间距仍是 2。

fast 到尾 · slow 在待删前一个:再走一步:slow 到 3,fast 到最后一个 5(fast.next=null,停)。slow 停在 3,它的下一个 del=4 正是倒数第 2 个——要删的就是它。

删除 · slow.next = slow.next.next:执行 slow.next = slow.next.next:把 4 摘掉(虚线划掉),3 的箭头越过它直接接到 5。链表变成 1 → 2 → 3 → 5

让两个指针保持 n 的间距一起走,领头的到尾、跟随的就到了「倒数第 n」的位置——这把「从后数」巧妙转成了「一起走到头」。

参考代码(Python)

Python
1dummy = ListNode(0, head)             # 哨兵,防删的是头结点
2slow = fast = dummy
3for _ in range(n): fast = fast.next   # fast 先走 n 步
4while fast.next:                      # 同速走到尾
5    slow = slow.next; fast = fast.next
6slow.next = slow.next.next            # 摘除
7return dummy.next

复杂度分析

  • 时间复杂度:O(n) —— 一趟扫描
  • 空间复杂度:O(1) —— 两个指针

套路模板

记住骨架:哨兵 + fast 先走 k 步 + 同步到尾,slow 就停在倒数第 k 的前驱。删除、找倒数第 k 个都套它。

Python
1dummy = ListNode(0, head)             # 删除类先挂哨兵
2slow = fast = dummy
3for _ in range(k): fast = fast.next   # 先拉开 k 的间距
4while fast.next:                      # 一起走到尾
5    slow, fast = slow.next, fast.next
6# 此时 slow 在倒数第 k 个的前一个

易错点

  • 不加哨兵,删头时崩 → ✅ 用 dummy 指向 head(删的是头结点时没有"前驱",哨兵补上这个前驱)
  • fast 走 n 还是 n+1 步搞混 → ✅ 从 dummy 出发走 n 步(基准点不同步数差 1,最易错)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →83. 删除排序链表重复元素 ← 返回题库