题目链接
剑指 Offer II 021. 删除链表的倒数第 n 个结点 mid
题目描述
给定一个链表,删除链表的倒数第 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 < = s z < = 30 1 <= sz <= 30 1<=sz<=30
- 0 < = N o d e . v a l < = 100 0 <= Node.val <= 100 0<=Node.val<=100
- 1 < = n < = s z 1 <= n <= sz 1<=n<=sz
分析:快慢指针
在解决链表问题时,我们都可以在真正的头节点 head
前面添加一个 虚拟头节点 dummy
,便于我们的操作。
-1
是虚拟头节点,1
才是真正的头节点,5
是我们要删除的倒数第二个结点。
我们定义两个快慢指针 fast
和 slow
,初始时两个指针都指向 真正的头节点head
,快指针 fast
先移动 n
步。
此时再定义一个指针 pre
指向 slow
的前驱节点,接着 slow
和fast
一起移动,直到 fast
指向null
。
此时 slow
指向的就是倒数第 n
个结点,pre
指向的就是倒数第 n+1
个结点。
所以我们直接删除第 n
个结点。
pre->next = pre->nex->next
最后返回头节点 dummy->next
即可。
时间复杂度: O ( n ) O(n) O(n)
C++代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* fast = head , *slow = head;
ListNode* pre = dummy;
//快指针先走 n 步
while(n){
fast = fast->next;
n--;
}
//快慢指针一起走,当 fast == nullptr时 , slow 指向的就是倒数第n个结点,pre指向的是倒数第n+1个结点
while(fast){
pre = slow;
fast = fast->next;
slow = slow->next;
}
//删除倒数第 n 个结点
pre->next = pre->next->next;
//返回头结点
return dummy->next;
}
};
Java代码:
/**
* 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(-1);
dummy.next = head;
ListNode fast = head;
ListNode slow = head;
ListNode pre = dummy;
//快指针先走 n 步
while(n>0){
fast = fast.next;
n--;
}
//慢指针 和 快指针同时走 当fast == null时,slow指向 倒数第 n 个结点 , pre 指向倒数第 n+1个结点
while(fast != null){
pre = slow;
fast = fast.next;
slow = slow.next;
}
//删除倒数第 n 个结点
pre.next = pre.next.next;
return dummy.next;
}
}