LeetCode热题(JS版)- 19. 删除链表的倒数第 N 个结点

178 阅读1分钟

题目

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

示例 1:

image.png

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

示例 2:

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

示例 3:

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

提示:

链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz

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

思路

本题我们可以采用双指针的方式来实现。我们可以定义两个指针,分别为 first 和 second,初始时都指向链表的头节点。我们先将 first 指针向前移动 n 步,然后再同时移动 first 和 second 指针,直到 first 指针到达链表的末尾。此时,second 指针即指向倒数第 n 个节点的前一个节点。最后,我们将 second 的 next 指针指向其 next 的 next,即可删除倒数第 n 个节点。 需要注意的是,如果链表的长度小于等于 n,那么我们需要删除的是链表的头节点,因此需要特殊处理。

  • 时间复杂度为 O(n),其中 n 是链表的长度。
  • 空间复杂度为 O(1),只需要使用常数个额外的指针变量。
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
    let a = head, b = head;
    // a先走n个
    for(let i = 0; i < n; i++) {
        a = a.next;
    }

    // 不足n个,删除头节点
    if(!a) return head.next;

    // a走完,b就是倒数第n个的前一个
    while(a.next) {
        a = a.next;
        b = b.next;
    }

    b.next = b.next ? b.next.next : null;

    return head
};

image.png