news 2026/10/12 4:36:03

InterviewGuide 精选力扣 237:删除链表中的节点——无头指针场景下的“替身攻击“删除法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
InterviewGuide 精选力扣 237:删除链表中的节点——无头指针场景下的“替身攻击“删除法
  • 文档
  • 教程
  • 知识库

【免费下载链接】InterviewGuide

🔥🔥「InterviewGuide」是阿秀从校园->职场多年计算机自学过程的记录以及学弟学妹们计算机校招&秋招经验总结文章的汇总,包括但不限于C/C++ 、Golang、JavaScript、Vue、操作系统、数据结构、计算机网络、MySQL、Redis等学习总结,坚持学习,持续成长!

项目地址:https://gitcode.com/forthespada/InterviewGuide
点击查看免费下载

本文讲解阿秀精选力扣 300+ 算法题中的链表 Easy 档题目 237. 删除链表中的节点,核心是在不给你头指针 head、只给你待删节点本身的约束下完成节点删除。读完本文,你将掌握"值覆盖 + 跳过下一节点"的替身攻击删除法,理解它为什么只能用于非末尾节点,并能把这一技巧迁移到其他链表面试题中。

一、题目背景与题意理解

在 精选力扣 300+ 道算法题 系列中,链表分类下的 Easy 题目共有三道:21. 合并两个有序链表、206. 反转链表、237. 删除链表中的节点(完整索引见 链表分类介绍页)。本题是其中思路最"反直觉"的一道。

题目要求:请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

现有一个链表head = [4,5,1,9],它可以表示为:

4 -> 5 -> 1 -> 9

示例 1

输入: head = [4,5,1,9], node = 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

示例 2

输入: head = [4,5,1,9], node = 1 输出: [4,5,9] 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.

二、题目的四条硬性约束(务必逐条理解)

原题"说明"部分给出了四条约束,它们不是废话,而是本题解题思路的前提,缺一不可:

  • 链表至少包含两个节点:保证被删节点后面一定还有节点可"顶替";
  • 链表中所有节点的值都是唯一的:保证按值"复制"后不会与其他节点值冲突,也保证删除后结果唯一可验证;
  • 给定的节点为非末尾节点并且一定是链表中的一个有效节点:这是替身攻击可行的最关键前提,末尾节点没有后继可借;
  • 不要从你的函数中返回任何结果:函数签名是void deleteNode(ListNode* node),直接在原链表上操作,无需、也无法返回新头结点(因为你根本拿不到 head)。

三、常规删除法为什么在这里失效

在一般认知里,删除单链表节点需要两步:

  1. 找到待删节点的前驱节点prev;
  2. 令prev->next = node->next,再释放 node。

问题在于:找到前驱节点必须从 head 开始遍历。而本题的函数签名只给了ListNode* node,没有给 head,单链表又无法从当前节点"回溯"到前驱,因此"先找前驱再删"的常规思路在这里完全走不通。

四、核心思路:替身攻击(值覆盖 + 跳过下一节点)

既然物理上无法删除"自己"(没有前驱可改),那就换个思路——让下一个节点替自己去死:

  • 第一步,把下一个节点的值node->next->val复制到当前节点node->val,当前节点"变成"了下一个节点的值;
  • 第二步,让当前节点的 next 指针直接指向下下个节点node->next->next,把下一个节点从链表中"跳过"。

从外部视角看,链表中"值等于原 node 值"的节点消失了,链表长度减一,功能与删除 node 完全等价。整个过程没有用到 head,时间复杂度 O(1),空间复杂度 O(1)。

以链表 4 -> 5 -> 1 -> 9、删除值为 5 的节点为例

删除前: 4 -> 5 -> 1 -> 9 (node 指向值为 5 的节点) 第 1 步: 把 node 的值改为 node->next 的值 1 4 -> 1 -> 1 -> 9 (注意这里 node 值已变) 第 2 步: node->next 指向 node->next->next 4 -> 1 -> 9 (值为 1 的第二个节点被跳过) 删除后: 4 -> 1 -> 9,与示例 1 输出一致

五、仓库题解:第一版,替身攻击

阿秀在 237. 删除链表中的节点题解 中给出的 C++ 解法正是"替身攻击":

void deleteNode(ListNode* node) { node->val = node->next->val; node->next = node->next->next; }

整个函数只有两行,逐行拆解:

行代码作用
第 1 行node->val = node->next->val;用后继节点的值覆盖当前节点,完成"身份替换"
第 2 行node->next = node->next->next;越过后继节点,把后继节点从链表中摘除

阿秀在力扣中文站提交时的平台记录为:执行用时 12 ms,击败当时 98.53% 的 C++ 提交;内存消耗 9.2 MB,击败 47.23% 的提交。需要说明的是,这类百分比数据取决于当时的提交样本与平台统计口径,仅作为参考,重点在于该解法的时间、空间复杂度均为常数级。

关于内存释放的补充说明

在严格意义上,第 2 行跳过了后继节点后,被跳过的节点在 C++ 中并未显式delete。在力扣的评测环境下,节点由平台统一管理,不释放也不会影响正确性;但在实际工程项目中,若该节点由new分配且无其他引用,应谨慎考虑释放策略(例如将其delete后再把node->next指向node->next->next,注意操作顺序),避免内存泄漏。本题为了简洁,采用不释放的写法是力扣社区的主流做法。

六、为什么必须是非末尾节点

替身攻击成立的根本前提是node->next不为空:

  • 若node是末尾节点,则node->next为nullptr,第 1 行直接访问node->next->val会产生空指针解引用;
  • 退一步说,即使不崩溃,末尾节点后面也没有"替身"可以顶上来,值覆盖无从谈起。

这正是题目约束"给定的节点为非末尾节点"的原因——它保证了算法的安全性,也意味着本题的解法天然不适用于删除末尾节点。若面试官追问"删除末尾节点怎么办",答案是需要额外的标记位(如哑节点)或从 head 遍历找前驱,而这恰恰是题目刻意不给你 head 的原因:让你意识到链表删除操作的多样性。

七、等价实现(Java / Python / Go 思路一致)

仓库以 C++ 解法为主,以下给出基于同一思路的常见等价实现,供不同语言背景的读者对照练习:

// Java class Solution { public void deleteNode(ListNode node) { node.val = node.next.val; node.next = node.next.next; } }
# Python class Solution: def deleteNode(self, node): node.val = node.next.val node.next = node.next.next
// Go func deleteNode(node *ListNode) { node.Val = node.Next.Val node.Next = node.Next.Next }

三种语言的核心逻辑与 C++ 完全一致:先覆盖值,再跳指针。这也说明替身攻击不是某种语言的奇技淫巧,而是对链表数据结构本质(指针/引用的可重定向能力)的通用利用。

八、易错点与面试追问清单

面试中围绕本题常见的考察点:

  1. 为什么能删"自己"?答:不物理删除当前节点,而是让后继节点"替身"被跳过,对外表现等价于删除了目标值。
  2. 为什么不能删末尾节点?答:无后继可借,node->next->val会空指针解引用。
  3. 值唯一性约束的意义?答:保证"按值覆盖"后链表仍满足唯一性,删除结果无歧义,便于验证。
  4. 时间复杂度与空间复杂度?答:均为 O(1),不依赖链表长度,也不需要额外容器。
  5. 这个技巧还能用在哪?答:凡是"只给你一个中间节点、要求原地改造"的场景,都可考虑"把后继的内容搬过来再摘除后继"的思路。

九、仓库联动:链表 Easy 三件套一起刷

本题与同目录下的另外两道 Easy 题恰好构成链表基础操作的三个维度,建议按顺序刷完(入口见 链表分类介绍页):

  • 21. 合并两个有序链表:掌握 ListNode 结构体的定义(ListNode(int x) : val(x), next(nullptr) {})与迭代式链表拼接,理解链表的构建与重组;
  • 206. 反转链表:pre / curr / next 三指针迭代,理解链表的指针重定向;
    1. 删除链表中的节点:理解链表的原地删除及其约束。

三道题全部是 O(1) 空间、单次遍历级别的操作,是校招笔试面试中链表题的最小可复用技能包。如果时间紧张,可以参考 算法部分使用指南 按人群选择刷题路径。

十、小结

237 题表面只有两行代码,背后却是一次重要的思维转变:当常规手段(找前驱)被剥夺时,通过"值覆盖 + 指针跳跃"从结果上达成同一目标。这提醒我们,面试考链表删除时,考官不仅看你会不会写代码,更看你能不能跳出"必须物理删除该节点"的思维定式——替身攻击,正是对这种定式的精准打击。

  • 文档
  • 教程
  • 知识库

【免费下载链接】InterviewGuide

🔥🔥「InterviewGuide」是阿秀从校园->职场多年计算机自学过程的记录以及学弟学妹们计算机校招&秋招经验总结文章的汇总,包括但不限于C/C++ 、Golang、JavaScript、Vue、操作系统、数据结构、计算机网络、MySQL、Redis等学习总结,坚持学习,持续成长!

项目地址:https://gitcode.com/forthespada/InterviewGuide
点击查看免费下载

相关推荐

上一篇:3分钟掌握DLSS Swapper:免费游戏优化工具终极指南
下一篇:3分钟精通:DLSS Swapper智能版本管理实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 4:33:26

测试面试现场:优雅排查Bug的五步定位法实战

测试面试官把笔记本电脑屏幕转过来的那一刻,我就知道接下来的话题要变了。屏幕上要么是一段代码,要么是一张线上报错日志的截图,紧跟着大概率是这么一句话——“这个Bug,如果现在出现在线上,你准备怎么排查&#xff1f…

作者头像 李华
网站建设 2026/10/12 4:32:25

零基础AI漫剧量产全流程:从工具选型到避坑指南

刚才在创作营里,老师让我们写下“你印象最深的动态漫画面”,然后把它丢进AI工具里跑了一版,看到成片的那一刻,我突然意识到:以前需要一整个动画团队才能做的漫剧,现在一个人、一台普通电脑、一堆订阅工具就…

作者头像 李华
网站建设 2026/10/12 4:31:12

前端处理裸Blob音频流:react-wavesurfer回放与踩坑指南

这个系列写到第二篇,我把最折磨人的一块单独拎出来聊:后端只返回一个光秃秃的 Blob 给你,没有文件名,没有时长,没有 ID,甚至连 Content-Type 都有可能是错的。前端要在 react-wavesurfer 录音组件里把这个 …

作者头像 李华
网站建设 2026/10/12 4:27:24

2026新PEP人教版四年级下册英语课件素材筛选与二次加工实用指南

备课群里最热闹的时候,往往就是新学期教材刚定版的那几周。今年轮到四年级下册,不少老师在找2026新PEP人教版四年级下册英语的课件和配套素材。我的网盘里也躺了好几份号称“完整版”的资料,下载完一打开,有的缺听力音频&#xff…

作者头像 李华