remove nth node from end of list

25 年 6 月 29 日 星期日
546 字
3 分钟

problem

Screenshot 2026-03-06 at 11.33.08 pm
js
var removeNthFromEnd = function (head, n) {
  // 1. 创建哨兵(dummy)节点,值为 0,next 指向原链表头节点
  // 作用:统一处理「删除头节点」和「删除中间节点」的逻辑,避免边界判断
  const dummy = new ListNode(0, head)

  // 2. 初始化快慢指针(left 慢指针,right 快指针),都指向哨兵节点
  let left = dummy
  let right = dummy

  // 3. 先让快指针(right)向右移动 n 步
  // 此时快慢指针之间的距离为 n,为后续找倒数第 n 个节点做准备
  while (n--) {
    right = right.next // 每循环一次,n 减 1,直到 n 为 0 停止
  }

  // 4. 快慢指针同时向右移动,直到快指针走到链表末尾(right.next 为 null)
  // 此时慢指针(left)的下一个节点就是「倒数第 n 个节点」
  while (right.next) {
    left = left.next // 慢指针走一步
    right = right.next // 快指针走一步
  }

  // 5. 删除倒数第 n 个节点:将慢指针的 next 指向其下下个节点
  // 跳过要删除的节点,链表中该节点会被垃圾回收
  left.next = left.next.next

  // 6. 返回新链表的头节点(哨兵节点的 next)
  // 避免原头节点被删除后返回 null 的情况
  return dummy.next
}

dummy的作用

dummy 哨兵节点的核心作用是统一处理链表头部被删除的特殊情况,让删除逻辑对链表中所有节点(包括头节点)都保持一致,避免额外的条件判断。

场景 1:不使用 dummy 节点的问题

假设链表是 [1](只有一个节点),要删除倒数第 1 个节点(也就是头节点):

  • 没有 dummy 时,删除头节点需要直接修改 headnull
  • 如果链表是 [1,2,3],要删除倒数第 3 个节点(也是头节点),同样需要修改 headhead.next
  • 但如果删除的是中间节点(比如倒数第 2 个节点 2),只需要让 1.next = 3 即可。

这就导致删除头节点和删除中间 / 尾节点的逻辑不一致,你需要额外写 if 语句判断是否删除的是头节点,代码会更复杂且容易出错。

文章标题:remove nth node from end of list

文章作者:Sirui Chen

文章链接:https://blog.siruichen.me/posts/19remove_nth_node_from_end_of_list[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。