刷题使我快乐,满脸开心.jpg

  • 来源:力扣(LeetCode)
  • 链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目

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

示例 1:

输入: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

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

思路

默认进阶属于题目要求的一部分~

1、最直接的思路应该是,用数组也好、栈也好,辅助找到并记录倒n的位置,然后摘掉倒n节点即可。不过这样空间复杂度会是O(n)

2、而往往链表问题都能找到空间复杂度的优化方法

比如,常见思路,快慢指针
这道题明显是可以用的,因为快慢指针的快与慢的逻辑定义是可以固定的,即慢指针比快指针慢n步

那就让快指针先走n步

不过有一点是要注意:

要删除倒n节点,慢指针需要指向倒n节点的前一个节点

我尝试了用慢指针从原链表头开始的处理方式,发现会有各种极端情况影响处理,所以不如在链表头之前再加一个辅助节点。这样慢指针的定义,就变成了指向倒n节点的前一个节点

至此,上代码

代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    veryHead := &ListNode{Next: head}
    fast := head
    slow := veryHead
    for n > 0  {
        fast = fast.Next
        n--
    }
    // 没到头则slow跟随走动
    // fast停下时
    // slow的下一个节点就是要去除的节点
    for fast != nil {
        fast = fast.Next
        slow = slow.Next
    }
    slow.Next = slow.Next.Next
    return veryHead.Next
}