【刷题记录】19. 删除链表的倒数第 N 个结点

111 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述

来源:力扣(LeetCode)

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

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 进阶: 你能尝试使用一趟扫描实现吗?

二丶思路分析

在删除节点的时候,我们需要知道节点的长度才能确定倒数第n个节点的位置。

如果遍历一次,在查找一次,也能做到。题目进阶的要求是尝试一次扫描来实现。

那么如果一次扫描来实现我们可以借助于类似窗口的概念来实现

  • 这个窗口我们让它是定长 n 的一个窗口,
  • 窗口左边为链表的起点。
  • 然后移动这个窗口,当窗口右边移动到链表的末端节点时候为空时候,窗口的左边指向的即是要被删除的 倒数第n个节点

如示例 1

image.png

三、代码实现

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        ListNode R = head;
        ListNode L = dummy;
        for (int i = 0; i < n; ++i) {
            R = R.next;
        }
        while (R != null) {
            R = R.next;
            L = L.next;
        }
        L.next = L.next.next;
        ListNode res = dummy.next;
        return res;
    }
}

复杂度分析

  • 时间复杂度:O(n)O(n),其中 n 是链表的长度
  • 空间复杂度:O(1)O(1)

运行结果

image.png

总结

这个题目也是利用双指针 + 窗口都类似概念(定长的),利用这个窗口的长度和移动,来确定倒数第n个节点所在的位置。来达到一次的遍历实现。