剑指 Offer 22. 链表中倒数第k个节点
删除链表的倒数第 N 个结点
- 思路
对链表操作时,为了首尾节点操作与其他节点相同,需要添加头节点(哑节点dummy node)。
- 先确定链表的长度,然后找到要删除节点的前驱节点,进行删除。需要添加哑节点
- 双指针(快慢指针):快指针比慢指针快n+1个,因为慢指针要指向被删除元素的前驱节点,遍历整个链表,当快指针指向空时,慢指针正好指向被删除节点的前驱节点。初始化慢指针指向哑节点,快指针指向链表第一个节点
- 栈
- 代码
第一个方法;
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0,head);
ListNode* low = dummy;
ListNode* res = nullptr;
int len = 0;;
while(head){
++len;
head = head->next;
}
for(int i = 0;i<len-n;++i){
low = low->next;
}
low->next = low->next->next;
res = dummy->next;
return res;
}
快慢指针;
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0,head);
ListNode* low = dummy;
ListNode* fast = head;
ListNode* res = nullptr;
int i = 0;
while(i<n){
++i;
fast = fast->next;
}
while(fast){
low = low->next;
fast = fast->next;
}
low->next = low->next->next;
res = dummy->next;
return res;
}
- 总结
1:对列表操作为了首节点操作不失一般性,需要添加哑节点
2:链表确定长度
3:删除链表某个节点 p->next = p->next->next; 不一定非要找到指向被删除节点的下一个节点的指针p1使p->next = p1;
环形链表
- 思想
判断循环链表;
- 判断链表的长度
- 算法-floyd判环(圈)算法(又称龟兔赛跑算法) 当龟兔进入环后,一快一慢,必定会相遇。
- 代码
- 长度
bool hasCycle(ListNode *head) {
int len = 0;
while(head){
++len;
head = head->next;
if(len>10000) return true;
}
return false;
}
- 龟兔赛跑算法
bool hasCycle(ListNode *head) {
if(head==NULL || head->next==NULL) return false;
ListNode * low = head;
ListNode * fast = head->next;
while(fast){
if(low == fast) return true;
if(fast->next==NULL || fast->next->next==NULL) return false;
fast = fast->next->next;
low = low->next;
}
return false;
}
142
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head==NULL ||head->next==NULL) return NULL;
ListNode* low = head;
ListNode* fast = head;
while(fast){
if(fast->next==NULL || fast->next->next==NULL) return NULL;
low = low->next;
fast = fast->next->next;
if(low==fast){
low = head;
//low = low->next;肯定报错
//fast = fast->next;
//if(low==fast) return low;
while(low != fast){//这个处理的很棒
low = low->next;
fast = fast->next;
}
return low;
}
}
return NULL;
}
};
- 总结
- 链表中是否有环的判断
- 环起点判断