如有想看算法具体分析请看
龟兔赛跑算法逻辑分析
上一题
Leetcode-141.环形链表
已经分析了是否链表中会存在一个环结构。
这道题依然会使用龟兔赛跑算法。
但并不是与上一题一样。会继续对算法进行拓展。
题目要求,要找到环的入口,这就比上一道题要恶心多了。
继续要使用快慢指针。
fast=fast->next->next;//一次走两个结点
slow=slow->next;//慢指针一次走一个结点
为什么还要使用快指针一次走两个结点的方法呢?
想找环的入口的结点,则必须要先证明有环,才能找结点。在不确定有环的情况下去找结点,明显不科学。而诺快指针走两个结点,慢指针走一个结点更符号题目测试用例的变化。若使用其他方法,容易不确定是否有环。
slow刚入环
设线(环外)的结点数位T(即slow走T次就到环的入口结点)
两指针相差N个结点,相当于fast在slow的后面L-N个结点
当两指针相遇时
相遇时,慢指针走了X个结点。且,这必是在慢指针一圈之内相遇的。
设环有L个结点。
为什么两指针相遇的点是慢指针在一圈之内?
因为fast的速度是slow的两倍,这其实就是追击问题。且,每次两指针的运动之差为1,所以是不可能错过的。如果这是slow在第二圈的时候相遇的,那么快指针早已在这时间段走完两圈了。就凭这个,所以只能是一圈之内的。
因为,因为fast是slow的两倍,所以,每循环一次,两者距离就缩小1,从某种意义上,就相当于,快指针每次走一个结点,而慢指针不动。最后会在L-N次移动后两指针重合。
则,他们两,fast与slow在环中走了L-(L-N)个节点,也就是N个节点。
且fast在环中走的N个结点,就相当于slow在环外走的T个结点。
则对于slow而言,只要再走L-(L-N)==N个结点就到达环的入口结点。因为先前推出fast只要走L-N次循环就能相遇,且slow也要走L-N次。
我们不知道环有多大,也不知道fast走了多少圈,但是,fast始终只走两个结点。如果fast走了多圈,即T会远大于L,
但对其弱化后,和fast走一圈是一个层次的意思。
即可推出T ==N。
即slow走N个结点,等于fast一次一个结点从头结点开始走,当两者相遇的结点,就是环的入口。
代码实现
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode* fast=head,*slow=head;
while(fast&&fast->next)//第一次在环中相遇
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
fast=head;
while(fast!=slow)//负责第二次相遇也就是环的头结点
{
fast=fast->next;
slow=slow->next;
}
return fast;
}
}
return NULL;
}
感谢各位大佬观看,如有问题,烦请指点一二。谢谢。