Leetcode: 删除链表的倒数第 N 个结点

17 阅读2分钟

原题:leetcode.cn/problems/re…

题目描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

解题思路

  1. 双指针技巧
    • 快指针先移动 N 步
    • 慢指针从头开始同步移动
  2. 虚拟头节点
    • 创建哑节点简化头节点删除操作
    • 始终返回 dummy.next 作为结果
  3. 同步移动
    • 快慢指针同步移动直至快指针到链表尾
    • 此时慢指针指向待删除节点的前驱
  4. 删除操作
    • 修改慢指针的 next 指向下下节点
    • 跳过需删除节点完成移除

关键洞察

  1. 倒数位置转换
    • 倒数第 N 个 ≡ 正数第 (L-N+1) 个
    • 双指针避免显式计算链表长度 L
  2. 间距控制原理
    • 快指针领先 N 步形成固定间距
    • 当快指针到尾部时,慢指针恰在目标前驱
  3. 边界处理
    • 虚拟头节点统一处理头节点删除
    • 处理 N>L 的情况(快指针提前到 null)
  4. 一次遍历
    • 仅需单次遍历即可完成删除
    • 时间复杂度严格 O(L)

复杂度分析

指标说明
时间复杂度O(L):L 为链表长度,只需一次遍历
空间复杂度O(1):仅使用常数空间存储指针
最佳情况O(1):当删除头节点时

代码实现

/**
 * 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) {
    const dummy = new ListNode(0, head); // 创建虚拟头节点,指向head
    let fast = dummy, slow = dummy;

    // 快指针先走 n+1 步
    for (let i = 0; i <= n; i++) {
        fast = fast.next;
    }

    // 快慢指针同时移动,直到快指针到达链表末尾
    while (fast) {
        fast = fast.next;
        slow = slow.next;
    }

    // 删除倒数第n个节点
    slow.next = slow.next.next;

    return dummy.next; // 返回真正的头节点
};

实际应用场景

  1. 操作系统:内核调度中移除优先级最低的任务`
  2. 数据库管理:查询结果集中删除指定排名的记录`
  3. 实时监控:性能监控系统中移除响应最慢的节点`
  4. 游戏开发:玩家排行榜中移除指定名次的玩家`

相似题目