今日快报:女大勇闯蓝桥杯C/C++A组,空手而归,痛失300大洋!心碎成渣渣,遂写博客!😭😭
目录
1.141.环形链表
⛱️试题链接戳这里!
🍉精华思路
1️⃣设fast指针1次走2步,slow指针1次走1步❌环形链表
2️⃣当fast为NULL或者fast->next为NULL✅环形链表
🌴深度剖析
❓️为什么fast一次走2步,而不是3步或者更多?
设环长度为C,步数差为X
当slow进环时,fast已在环中顺时针走了N步
那么此时fast距离slow有C-N步
每移动一次,它们之间的距离就会缩短x
当slow=1,fast=2时,x=2-1=1:
那么,再移动(c-N)/1=c-N次,fast就可以追上slow
当slow=1,fast=3时,x=3-1=2:
1.当C-N为偶数时
再移动(C-N)/2次,fast就可以追上slow
2.当(C-N)为奇数时
那么这次肯定就追不上。
并且fast和slow之间的距离变为C-1
当c-1为偶数,即C为奇数时
再移动(C-1)/2次就能追上了
当C-1为奇数,即C为偶数时
那么又会遇不到slow,并且再次超过它1步,距离又变为C-1,陷入死循环,永远追不到
因此,步数差保证为1,即设置slow走1步,fast走2步,只要有环存在,是一定可以相遇的,而步数差>=2,则有可能永远相遇不到。
🥳代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
if(head == NULL){
return false;
}
struct ListNode* fast = head;
struct ListNode* slow = head;
while(fast != NULL && fast->next!=NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
return true;
}
}
return false;
}
2.142.环形链表II
⛱️试题链接戳这里!
🍉精华思路
前半段思路和上道题一样,
设置slow,fast指针,
slow指针每次走1步,fast指针每次走2步
如果可以相遇则说明有环存在。
当相遇后,另外设置一个指针p1,从起点出发,一次走1步
而相遇处也设置一个指针p2,一次走1步
p1和p2指针相遇的位置就是环链表的起点位置。
🌴深度剖析
下面对上面的思路进行验证:
设线段长L,设环长度为C
设当slow,fas相遇时,fast已在环中走了x个完整的圈
slow在环内刚走了N步
相遇时,slow路程:L+N
fast路程:L+xC+N
可列出方程式:
L+XC+N=2(L+N)
XC-L-N=0
(X-1)C+C-N-L=0
L=(X-1)C+C-N
那么,以相遇点为起点的p2,走到环链表的路程为(C-N)+XC (X=0,1,2,3…)
P1走到环链表的路程为L
由上式可得:L=(X-1)C+C-N
即两点的确可同时到达环链表起点处
🥳代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
if(head == NULL){
return NULL;
}
struct ListNode* fast = head;
struct ListNode* slow = head;
struct ListNode* p1 = head;
while(fast != NULL && fast->next!=NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
struct ListNode* p2 = slow;
while(p1!=p2){
p1=p1->next;
p2=p2->next;
}
return p1;
}
}
return NULL;
}
看到这里,不要忘了点赞收藏~