news 2026/5/12 18:57:18

链表专题(四):一把尺子的智慧——「删除链表的倒数第 N 个结点」

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
链表专题(四):一把尺子的智慧——「删除链表的倒数第 N 个结点」

场景想象:

你手里有一根链表,但你不知道它有多长(不能直接得到 length)。

任务是:找到倒数第 N 个节点,把它删掉。

  • 如果是数组,我们可以直接算下标length - N

  • 但链表是单向的,我们不知道终点在哪。

  • 笨办法:先跑一趟量长度L,再跑一趟去L - N的位置。虽然是 $O(N)$,但遍历了两次。

  • 聪明办法(快慢指针):

    想象你手里有一把长度为 N 的“尺子”(或者一根棍子)。

    1. 快指针先跑N步(撑开尺子)。

    2. 然后让快指针慢指针同时往后移。

    3. 快指针碰到链表尽头(null)时,慢指针(尺子的另一头)正好就停在了倒数第 N 个节点的位置!

核心痛点:

要删除一个节点,我们需要找到它的前一个节点 (Pre)。

所以,我们的“尺子”实际上要稍微再长一点,或者让快指针多走一步,这样慢指针才能停在目标节点的前一位。

力扣 19. 删除链表的倒数第 N 个结点

https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

题目分析:

  • 输入:链表头head,整数n

  • 目标:删除倒数第n个节点。

  • 输出:新头节点。

例子:1 -> 2 -> 3 -> 4 -> 5,n = 2

  • 倒数第 2 个是4

  • 删除后:1 -> 2 -> 3 -> 5

核心思维:虚拟头结点 + 快慢指针 (Gap法)

  1. 虚拟头结点 (Dummy)

    • 为什么又要它?因为如果要删的是倒数最后一个(也就是正数第一个,头结点),没有 Dummy 会很麻烦。

  2. 快指针先跑n + 1

    • 为什么是n + 1

    • 因为我们希望当快指针指向null(越界)时,慢指针正好停在倒数第 n 个节点的前一个

    • 这样我们才能执行slow.next = slow.next.next

代码实现 (JavaScript)

JavaScript

/** * Definition for singly-linked list. * function ListNode(val, next) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } */ /** * @param {ListNode} head * @param {number} n * @return {ListNode} */ var removeNthFromEnd = function(head, n) { // 1. 虚拟头结点:防止删除的是头结点(比如 list=[1], n=1) const dummy = new ListNode(0, head); // 2. 定义快慢指针,初始都指向 dummy let slow = dummy; let fast = dummy; // 3. 让快指针先走 n + 1 步 // 目的:拉开 n+1 的间距。这样当 fast 走到 null 时,slow 正好在目标的前一位 for (let i = 0; i <= n; i++) { fast = fast.next; } // 4. 双指针同时移动 // 只要 fast 还没掉出悬崖(null),就一起往后挪 while (fast !== null) { slow = slow.next; fast = fast.next; } // 5. 此时 slow 指向的是“倒数第 n 个节点”的【前驱节点】 // 执行删除操作 slow.next = slow.next.next; return dummy.next; };

深度模拟

假设list = [1, 2, 3, 4, 5],n = 2(删除 4)。

  • 初始dummy -> 1 -> 2 -> 3 -> 4 -> 5 -> null

  • Fast 先跑 3 步 (n+1)

    • 0步: dummy

    • 1步: 1

    • 2步: 2

    • 3步: 3

    • 此时fast在 3,slow在 dummy。

  • 一起跑

    • Round 1:fast->4,slow->1

    • Round 2:fast->5,slow->2

    • Round 3:fast->null,slow->3

  • 停!fast是 null 了。

  • 操作slow现在指着 3。

    • slow.next是 4 (目标)。

    • slow.next = slow.next.next(也就是 5)。

    • 链表变成1 -> 2 -> 3 -> 5。完美!

总结

这道题是**“固定间距双指针”**的教科书级应用。

  • 关键点:只要看到“倒数第 K 个”,马上反应过来 ->让快指针先走 K 步

  • 细节:为了方便删除,我们通常让快指针多走一步(或者判断条件改为fast.next !== null),目的是拿到前驱节点


下一题预告:相交链表

刚才我们用两个指针一前一后跑。

下一题 LC 160. 相交链表(专题五),我们要让两个指针在两条不同的路上跑。

  • 题目:给你两个链表 A 和 B,它们在某个节点汇合了(变成 Y 字形)。请你找到这个交点。

  • 难点:A 和 B 长度不一样,直接遍历会错开,怎么让它们在终点相遇?

  • 技巧:“走过你走的路”—— 极其浪漫的解法。

准备好继续了吗?

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

Linux crontab定时任务:每天凌晨自动更新模型镜像

Linux crontab定时任务&#xff1a;每天凌晨自动更新模型镜像 在AI模型快速迭代的今天&#xff0c;一个看似微小的版本更新&#xff0c;可能就决定了推理结果的成败。尤其是在数学推导、算法生成这类对逻辑严密性要求极高的场景中&#xff0c;哪怕只是优化了某类边界的处理方式…

作者头像 李华
网站建设 2026/5/8 22:28:33

iPad Pro手写输入优化:数学公式识别+VibeThinker求解

iPad Pro手写输入优化&#xff1a;数学公式识别 VibeThinker求解 在一场高校数学建模竞赛的现场&#xff0c;一名学生用Apple Pencil在iPad Pro上快速写下一道复杂的微分方程。笔尖刚落&#xff0c;屏幕便已呈现出完整的求解过程——从变量替换到积分变换&#xff0c;每一步推…

作者头像 李华
网站建设 2026/5/8 22:27:47

为什么你的Docker镜像越来越胖?一文找出元凶并解决

第一章&#xff1a;为什么你的Docker镜像越来越胖&#xff1f;当你频繁更新应用并构建新的 Docker 镜像时&#xff0c;是否发现镜像体积不断膨胀&#xff1f;这不仅影响部署速度&#xff0c;还增加了存储和传输成本。根本原因往往在于镜像构建过程中的“层”积累机制——每一次…

作者头像 李华
网站建设 2026/5/8 8:54:30

2026必备!本科生毕业论文神器TOP10:一键生成论文工具测评

2026必备&#xff01;本科生毕业论文神器TOP10&#xff1a;一键生成论文工具测评 2026年本科生论文写作工具测评&#xff1a;为何需要这份榜单&#xff1f; 随着高校教育的不断升级&#xff0c;本科生在毕业论文写作中的要求也日益提高。从选题构思到文献综述&#xff0c;再到格…

作者头像 李华
网站建设 2026/5/10 12:12:01

揭秘Docker资源占用异常:如何用3个工具精准定位问题根源

第一章&#xff1a;Docker资源监控的核心价值在现代云原生架构中&#xff0c;容器化应用的动态性和高密度部署特性使得资源管理变得复杂。Docker资源监控不仅帮助运维团队实时掌握容器的CPU、内存、网络和磁盘使用情况&#xff0c;还为性能调优、故障排查和容量规划提供了关键数…

作者头像 李华