题目描述
思路解析动画文字版
可以先求长度 L,再删第 L-n+1 个。双指针能一遍完成。
用 dummy 处理删除头结点。fast 先走 n 步后,二者一起走,fast 到尾时 slow 正好停在待删节点的前一个(前驱)。
dummy 统一头删法:dummy 指向 head。fast 和 slow 都从 dummy 出发。
fast 先走 2 步:n 等于 2,fast 从 dummy 先走到节点 2。slow 还在 dummy。
一起走 · 第 1 步:fast 走到 3,slow 走到 1。两者间距始终是 2。
一起走 · 第 2 步:再同步走一步,fast 到 4,slow 到 2。间距仍是 2。
fast 到尾:fast 到最后一个节点 5,停。slow 在节点 3,正好是待删节点 4 的前一个(前驱)。
跳过节点 4:执行 slow.next = slow.next.next,把 4 从链表中绕过去。
返回 dummy.next:删除后返回 dummy.next,得到 1→2→3→5。
dummy 让删除头结点也不用特判。
边界三连:删除头、删除尾、单节点,是这题必须跑的三连。
雷区实演 · 删除头结点:head=[1,2], n=2。fast 先走到 2,while 不动,slow 留在 dummy,跳过 head。
面试追问 1:它统一删除头结点的情况,返回 dummy.next 即可。
面试追问 2:可以配合 while fast != null,让 slow 也停前驱;关键是写法自洽。
面试追问 3:LeetCode 保证合法;工程代码需要检查 n 是否超过长度。
这题学完不要乱跳,下一步去 对应专题 连刷同类题;卡住时用 AI 答疑追问“为什么这一步成立”,比只背答案更稳。
参考代码
class Solution: def removeNthFromEnd(self, head, n): dummy = ListNode(0) dummy.next = head fast = slow = dummy for _ in range(n): fast = fast.next while fast.next: fast = fast.next slow = slow.next slow.next = slow.next.next return dummy.next复杂度
- 时间复杂度:O(n),fast 最多走完整条链表
- 空间复杂度:O(1),只用 dummy、fast、slow
可套用的代码模板
这是「倒数第 k 个」的可背骨架:fast 先领先 k 步制造固定间距,同步走到 fast 触尾,slow 必落在倒数第 k 个的前驱。换题时只改第 3 步——本题是删除(slow.next=slow.next.next),找倒数第 k 个值就读 slow.next.val。
# 倒数第 k 个 → fast 先领先 k 步,再同步走dummy = ListNode(0); dummy.next = headfast = slow = dummyfor _ in range(k): # 1. 拉开 k 的固定间距 fast = fast.nextwhile fast.next: # 2. 同步走到 fast 触尾 fast = fast.next slow = slow.next # slow 落在倒数第 k 的前驱# 3. 此刻 slow.next 就是目标,按需删/读/改return dummy.next易错点
面试追问把动画讲成自己的话
追问为什么 dummy 必要?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
复制带随机指针的链表
LeetCode 138 · 中等 · 沿着 链表 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题