(希望每天能挤点时间补充编程基础,以及这个学习笔记能够持续下去)
题目:
给你一个链表,删除链表的倒数第 `n` 个结点,并且返回链表的头结点。
最初想法:
(无)。
解法:双指针:
寻找目标节点+删除目标节点。
#寻找目标节点:
1:设置两个指针。两个指针的距离为n个节点。
指针1为快指针。领先旧指针n个距离。
指针2为慢指针。位置为第一个节点
原理:当指针1抵达节点的空指针时。意味着指针2找到了要删除的节点:
#删除目标节点
核心。找到那个节点后。倒退一格。
令point->next=point->next->next即可。
即跳过下一个指针。指向下下一个指针。
所以。最终要倒数第n+1个节点。
第一版本:
cpp
class Solution{
public:
ListNode* DeleteChainNode(ListNode* head,int target){
ListNode* fast=head;
ListNode* slow=head;
for(int i=0;i<=target;i++)
fast=fast->next;
};
while(fast!=nullptr){
fast=fast->next;
slow=slow->next;
}
slow->next=slow->next->next;
}
}
问题一:如果要删掉的是头节点。
例子:1 -> 2 -> 3, n = 3(删除倒数第3个,就是头节点1)
此时slow指针就要指向第-1个位置。也就是空指针。那么slow指针无效。
#解决方案
前置节点:
提前设置一个前置节点为最初链表的-1位置:
让前置节点指向链表的第一个头节点。即可
即
cpp
ListNode* dummy=new ListNode(0);
dummy->next=head;
ListNode* fast=dummy; ListNode* slow=dummy;
第二版:
cpp
class Solution{
public:
ListNode* DeleteChainNode(ListNode* head,int target){
ListNode* dummy=new ListNode(0);
dummy->next=head;
ListNode* fast=dummy;
ListNode* slow=dummy;
for(int i=0;i<=target;i++){
fast=fast->next;
};
while(fast!=nullptr){
fast=fast->next;
slow=slow->next;
}
slow->next=slow->next->next;
return head;
}
};
问题:如果删除的是头节点。那么。head的位置就是个空指针。返回错误。
所以。应该返回:前置节点的下一个指针,即:dummy->next;
Q:为什么不是dummy?
A:因为dummy并不是链表最初的一部分。是设置的外部调节。返回的如果是dummy->next就可以保证不会被删掉。