19.删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
示例
链表:1–>2–>3–>4–>5–>6
要求删除倒数第二个节点 即 n = 2;
链表:1–>2–>3–>4–>5–>6 即删除节点5 链表变为
链表:1–>2–>3–>4–>6
解题思路:双指针法 (快慢指针)
题解一:设置虚拟头指针 步进n+1
- 慢指针和快指针的初试位置都设置在 dummy 节点上
- 先让快指针先走n+1步
- 在保证快指针的指向不为空的情况下,将快慢指针同频向前移动,保持固定间隔,until快指针指向链表末尾
- 此时快慢指针的间隔为:n+1
- 让慢指针的前一个指针即 prev节点的指针跳过 慢指针slow 指向 slow.next 就实现了删除的目的!此时慢指针指向的节点就是要删除的节点!
/**
* 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 dummmy = new ListNode(-1);//设置虚拟头节点
dummmy.next = head;
ListNode slow = dummmy;//将快慢指针的位置初始化
ListNode fast = dummmy;
for(int i=0;i<n;i++){
fast = fast.next;
}
//在dmsxl中,是这么写这句话的 :
//while(n-->0){fast = fase.next};
//这个意思是:
// 它的意思是循环n次,除了最常用的 for (int i = 0; i < n; ++i) {...} 之外,还可以写 while (n-- > 0) {...} 和 while (--n >= 0) {...}。
ListNode prev = null;
while(fast != null){
prev = slow;
slow = slow.next;
fast = fast.next;
}
prev.next = slow.next;
// slow.next = null;
return dummmy.next;
}
}
关于 while(n–>0):
while(n–>0){fast = fase.next};
这个意思是:
它的意思是循环n次,除了最常用的 for (int i = 0; i < n; ++i) {…} 之外,还可以写 while (n-- > 0) {…} 和 while (–n >= 0) {…}。
题解二:
- 慢指针和快指针的初试位置都设置在 dummy 节点上
- 先让快指针先走n步
- 在fast.next !=0的情况下,将快慢指针同频向前移动,保持固定间隔
- 此时快慢指针的间隔为:n
- 让慢指针的指向 慢指针下一个节点的指向 ,慢指针下一个节点才是要删除的节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummmy = new ListNode(-1);
dummmy.next = head;
ListNode slow = dummmy;
ListNode fast = dummmy;
for(int i=0;i<n;++i){
fast = fast.next;
}
// ListNode prev = null;
while(fast.next != null){//这是和上一种方法的区别
// prev = slow;
slow = slow.next;
fast = fast.next;
}
// prev.next = slow.next;
slow.next = slow.next.next;
// slow.next = null;
return dummmy.next;
}
}