一、题目概述
个人原始的解法(浪费空间):
class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode*pMove=head; ListNode*tmp=nullptr;//用来释放需要删除的结点 ListNode*dummyHead=new ListNode(0,head);//连接到头部 int cnt=0; while(pMove!=nullptr) { cnt++; pMove=pMove->next; } ListNode**pArr=new ListNode*[cnt+10];//申请空间存储指针的地址 pArr[0]=dummyHead; pMove=head; for(int i=1;pMove!=nullptr;i++,pMove=pMove->next) { pArr[i]=pMove; } pMove=pArr[cnt-n];//指向待删除结点的前一个(注意区分是否是头结点) tmp=pMove->next;//待删除结点 if(tmp) pMove->next=tmp->next; delete tmp; tmp=nullptr; delete[]pArr; return dummyHead->next; } };
教训:cnt=2,n=2的时候,删除的头结点,和删除中间结点是不一样的,为了统一操作,最好还是加上一个虚拟的头结点
更优解:双指针(双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。)
二、双指针解法
算法流程:
①设置虚拟头结点(防止需要删除的是头结点)->为了统一操作
②
代码实现:
注意:n++是为了让fast先走一步,方便进行删除操作
class Solution
{
public:
ListNode* removeNthFromEnd(ListNode* head, int n)
{
ListNode*dummyHead=new ListNode(0,head);
ListNode*fast=dummyHead,*slow=dummyHead;//双指针操作
ListNode*tmp=nullptr;//用来手动释放内存
n++;//为了让slow指针在目标del结点的前一个,方便删除
while(n--&&fast!=nullptr)
fast=fast->next;
while(fast!=nullptr)
{
slow=slow->next;
fast=fast->next;
}
tmp=slow->next;
slow->next=tmp->next;
delete tmp;tmp=nullptr;
return dummyHead->next;
}
};