从起始点和相遇点开始走的两个指针会在入口点相遇:
模型如下:
首先用快慢指针判断该链表中是否带环:
定义slow和fast指针,slow和fast指针从起始点开始,slow每次走一步,fast每次走两步.这里跳过几步,直接来到slow刚入环的时候:
上图中,当slow指针走到环入口处时,fast来到最后一个节点,再走一步:
fast和slow相遇, 回到第一个图,假设slow刚走到环入口,而此时fast已经走了n步,由于fast每次都比slow多走一步,所以每循环一次,slow和fast之间的距离就-1.最后的slow和fast一定会相遇.
由上面的关系图可知,当在相遇点相遇时,slow走了L+X,而fast要与slow再环中相遇,由于fast走在slow前,所以,fast要比slow多走n*c,本质上是一个追及问题,fast走的步数-slow走的步数==n*c才会相遇,即fast要比slow多走n个周期,那么就有关系式:
2*(L+X)=L+X+n*c; fast走的步数是slow指针的二倍.
就有:L=n*c-x;
这个表达式的意思:一个指针从起始点开始走,一个指针从相遇点开始走,最终会在入口相遇.
代码:
struct ListNode *detectCycle(struct ListNode *head) {
//判断有无环
struct ListNode * slow,*fast;
slow=fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
break;
}
}
if(!fast||!(fast->next))
{
return NULL;
}
struct ListNode * meet=slow;
struct ListNode *cur=head;
while(meet!=cur)
{
meet=meet->next;
cur=cur->next;
}
return cur;
}