原题来自牛客网LeetCode:链接
题目描述
给定一个链表,删除链表的倒数第n个节点并返回链表的头指针。
例如,给出的链表为:1->2->3->4->5, n= 2.
删除了链表的倒数第n个节点之后,链表变为1->2->3->5.
备注:
- 题目保证n一定是有效的
- 请给出请给出时间复杂度为O(n)的算法
思路
使用双指针,先让一个指针走出n步,然后开始让两个指针一起移动,直到先出发的指针到达尽头。因为二者的距离一直为n,所以最终后出发的指针所处位置即倒数第n个结点。
需要注意,因为找到的是倒数第n个结点,而删除时我们需要知道倒数第n+1个结点,因此需要加以控制,因此下方代码判断的是while(p->next!=nullptr)而不是while(p->next!=nullptr)。
这题还有个坑点,有可能删除的是头结点,因此要通过判断先出发的指针是否已经变成nullptr,如果是那说明要删的是头结点(具体原因自己数数就知道了)。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head==nullptr||head->next==nullptr)
return nullptr;
ListNode *p=head,*pre=head,*tmp;
//第一个指针先动n步
for(int i=0;i<n&&p!=nullptr;i++)
p=p->next;
//讨论删除头结点的特殊情况
if(p==nullptr){
tmp=head->next;
delete head;
return tmp;
}
//一起移动
while(p->next!=nullptr){ //为了知道倒数第n+1个结点,所以判断p->next!=nullptr
p=p->next;
pre=pre->next;
}
tmp=pre->next;
pre->next=pre->next->next;
delete tmp;
return head;
}
};