题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例
说明
给定的 n 保证是有效的。
进阶
你能尝试使用一趟扫描实现吗?。
题解
1.用容器存储每个节点指针,空间复杂度较大
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
//自己的方法,虽然只遍历了一次,但是空间复杂度为O(n)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
vector<ListNode*> rongqi;
//i为容器的尺寸,不包括最后NULL指针的尺寸
int i=0;
for(ListNode* p=head;p!=NULL;p=p->next){
rongqi.push_back(p);
i++;
}
//此处相当于加一个NULL指针哨兵,方便只有一个节点情形的判断
rongqi.push_back(NULL);
//当删除的节点为第一个节点时
if(n==i){
delete head;
head=rongqi[1];
}
//通常情况下
else{
rongqi[i-n-1]->next=rongqi[i-n]->next;
delete rongqi[i-n];
}
return head;
}
};
2.用双指针方法
使双指针保持n+1的距离,然后后指针指向第n+1个空节点时,前指针就指向要删除节点的前节点。
//官方的方法,采用双指针,通过使双指针保持距离为n的间距,从而可以只用遍历一次
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int i=0;
ListNode* p1=head;
//当n=链表尺寸时,p1指向NULL,相当于哨兵
for(int i=0;i<n;i++){
p1=p1->next;
}
ListNode* p2=head;
//当删除倒数第n个节点时
if(p1==NULL){
head=head->next;
delete p2;
}
//通常情况下
else{
//使得p1与p2的间距为n+1
p1=p1->next;
while(p1!=NULL){
p1=p1->next;
p2=p2->next;
}
ListNode* temp = p2->next;
p2->next=p2->next->next;
delete temp;
}
return head;
}
};
双指针方法图解
参考链接
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/