leetcode:删除链表的倒数第 N 个节点

71 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

题目描述

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

示例1:

image.png

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

示例 2:

输入: head = [1], n = 1
输出: []

示例 3:

输入: head = [1,2], n = 1
输出: [1]

说明:

给定的 n 保证是有效的。

进阶:

你能尝试使用一趟扫描实现吗?

题目地址:leetcode-cn.com/problems/re…

解题思路

这里我们可以使用双指针算法,不妨设为指针 A 和 指针 B。指针 A 先移动 n 次, 指针 B 再开始移动。当 A 到达 null 的时候, 指针 B 的位置正好是倒数第 n。这个时候将 B 的指针指向 B 的下下个指针即可完成删除工作。

具体地,初始时 first 和 second 均指向头节点。我们首先使用 first 对链表进行遍历,遍历的次数为 nn。此时,first 和 second 之间间隔了 n−1 个节点,即 first 比 second 超前了 nn 个节点。

在这之后,我们同时使用 first 和 second 对链表进行遍历。当 first 遍历到链表的末尾(即 first 为空指针)时,second 恰好指向倒数第 n 个节点。

步骤:

  • 设置虚拟节点 dummyHead 指向 head(简化判断,使得头结点不需要特殊判断)
  • 设定双指针 p 和 q,初始都指向虚拟节点 dummyHead
  • 移动 q,直到 p 与 q 之间相隔的元素个数为 n
  • 同时移动 p 与 q,直到 q 指向的为 NULL
  • 将 p 的下一个节点指向下下个节点

代码:

var removeNthFromEnd = function (head, n) {

    let i = -1;
    const noop = {
        next: null,
    };

    const dummyHead = new ListNode(); // 增加一个dummyHead 简化操作
    dummyHead.next = head;
    let currentP1 = dummyHead;
    let currentP2 = dummyHead;

    while (currentP1) {
        if (i === n) {
            currentP2 = currentP2.next;
        }
        
        if (i !== n) {
            i++;
        }
        currentP1 = currentP1.next;
    }

    currentP2.next = ((currentP2 || noop).next || noop).next;
    return dummyHead.next;
};