开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情
19.删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 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]
快慢指针解法
可能大家看到这道题主要的头疼点在于要找的是倒数第n个节点,我们都知道单向链表不能像数组那样有索引可以正着倒着都遍历或是直接通过索引值找到对应节点。
所以这里我们用了一个巧妙的方法,设置两个指针,一快一慢,先让快指针往前走n次,然后让快慢指针一起走直到快指针下一位指向空,这样慢指针指向的就是倒数第n个节点,但是因为我们删除结点的话需要一个指向它上一个节点的指针,所以这里我们应该想办法让慢指针指向倒数第n+1节点。
因为删除的节点可能是头结点,所以我们也采用虚拟头结点,开始让fast和slow指针都指向虚拟头结点dummy,那么有了虚拟头结点,经过上述操作后,慢指针自然而然就指向倒数第n+1个节点了,我们下面的删除操作就很方便了。
/**
* 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);
dummy.next=head;
ListNode fast=dummy;
ListNode slow=dummy;
for(int i=0;i<n;i++){
fast=fast.next;
}
while(fast.next!=null){
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
return dummy.next;
}
}
这里我刚开始又数错了,我开始时让fast和slow都指向head,但是后面的代码都是一样的,这就导致slow后来指向的是倒数n-1,同时有报错,所以大家一定要细心。