LeetCode 19 Remove Nth Node From End of List (Tag:Linked List Difficulty:Medium)

167 阅读2分钟

这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战

前言

关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!

题目描述

给你一个链表,删除链表的倒数第 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]

链接:leetcode-cn.com/problems/re…

题解

  1. 快慢指针. 首先, 我们可以利用快慢指针来找出倒数第 n 个节点: 快慢指针一开始都指向 head 节点, 先让快指针走 n 步, 然后快慢指针一起走. 当快指针为空时, 慢指针此时指向的就是倒数第 n 个元素.

    但是, 这道题是让我们把倒数第 n 个元素从链表中删除, 所以我们要找的是倒数第 n + 1 个元素, 通过第 n+1 个元素把第 n 个元素从链表中删除. 那么, 如果我们初始时让慢指针指向 head, 快指针指向 head.next, 然后再按照上面的方法向后遍历, 就能找到第 n+1 个元素. 但是, 这个方法存在缺陷, 当链表只有一个元素, 比如 [1] 的时候, 快指针为空, 我们就需要特殊处理这种情况.

    所以, 一种更通用的方法是构造一个假的头部, 假头部的 next 指针指向 head. 我们用慢指针指向假头部, 快指针指向 head, 那么就不用额外考虑边界条件, 而是一种通用的解法.

    具体代码如下, 时间复杂度 O(n)

/**
 * 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)
    let slow = dummy
    let fast = head
    while (n--) fast = fast.next
     
    
    while (fast) {
        fast = fast.next
        slow = slow.next
    }
    
    let nth = slow.next
    if (nth) {
        nth_next = nth.next
        slow.next = nth_next
    }
    return dummy.next
};
  1. 栈. 栈是一种先进后出的数据结构, 所以利用栈我们能找到倒数第 n + 1 个元素. 具体做法是将所有节点入栈, 然后在出栈, 出栈的时候计数即可. 具体解法不再写出.