①双指针思路
1.双指针思路核心:
fast比slow先走 n个单位长度(距离相差n)
当fast遍历完链表的时候,slow指向的就是倒数第n个元素
2.一共需要四个变量
2.1.删除元素需要:
三个变量(包含slow)
2.2.slow和fast指针需要:
两个变量(slow、fast)
slow指针重复,所以一共只需要四个变量
补充知识:(但是看不懂也没关系,因为考虑内存释放肯定好过于不考虑)
如果不考虑内存释放,删除元素其实就不需要三个变量,而是两个变量。(但slow和fast就不是距离n个单位长度)
②代码实现
/**
* 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* fast = head;
ListNode* slow = head;
ListNode* slow_parent;
ListNode* slow_next;
while(n--){//fast比slow先走n个单位长度
fast = fast->next;
}
if(fast==NULL){//slow指向的是第一个元素//需要分类讨论,这就是非虚拟头结点需要分类的地方,但本题并不复杂,就展示一下使用非虚拟头结点!
ListNode* tmp = head->next;//
delete head;
return tmp;
}
while(fast){//当fast遍历完整个链表,slow指向的是该删除的元素,最后就是delete slow;
slow_parent = slow;
slow=slow->next;
slow_next=slow->next;
fast=fast->next;
}
delete slow;
slow_parent->next = slow_next;
return head;
}
};