一、前言
每日算法坚持第三天,该专栏争取日日更新,加油
二、简介和示例
简介
LeetCode 19题, 删除链表的倒数第 N 个结点: 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
链表数据结构
public class ListNode { public int val; public ListNode next; public ListNode() { } public ListNode(int val) { this.val = val; } public ListNode(int val, ListNode next) { this.val = val; this.next = next; } } 复制代码
示例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
三、解题
思路分析
- 为了方便对头节点操作, 还是使用虚拟头节点
dummy
来做 - 创建一个链表
slow
表示当前节点 - 根据提示可知 n < 链表长度的
- 所以使用一个链表
fast
去获取当前节点后第n个节点 - 搞一个链表
prev
专门记录当前节点的上一个节点 - 循环终止条件是
fast
链表的 next == null - 循环内操作
- prev 存储当前节点
- slow = slow.next
- fast = fast.next
- 循环结束之后, 上一节点是 prev, 下一节点是 slow.next
- 又因为我们的 dummy有一个虚拟头节点, 所以返回值为 dummy.next
这边我以为就结束了, 但是看大佬的代码, 还有一步 slow.next = null, 去释放掉了 slow.next
四、代码展示
public static ListNode removeNthFromEnd(ListNode head, int n) { // 为了方便对头节点操作, 还是使用虚拟头节点 `dummy` 来做 ListNode dummy = new ListNode(-1); dummy.next = head; // 创建一个链表 `slow` 表示当前节点 ListNode slow = dummy; // 使用一个链表 `fast` 去获取当前节点后第n个节点 ListNode fast = dummy; // 根据提示可知 n < 链表长度的, 所以使用fast去判断slow节点是不是倒数第n个节点 while (n-- > 0) { fast = fast.next; } // 记住 待删除节点slow 的上一节点 ListNode prev = null; // 循环终止条件是 `fast` 链表的 next == null while (fast != null) { // prev 存储当前节点 prev = slow; // slow和fast节点向下进一步 slow = slow.next; fast = fast.next; } // 循环结束之后, 上一节点是 prev, 下一节点是 slow.next, 删除show节点 prev.next = slow.next; // 下面是看大佬代码的收获 // 释放 待删除节点slow 的next指针, 这句删掉也能AC slow.next = null; return dummy.next; } 复制代码
五、提交代码
网络异常,图片无法展示
|
注: 本篇文章代码部分采用了代码随想录大佬的代码在变量命名, fast链表的确认和最后一步的释放内存上比我自己的方式精简且清晰明了很多