一、问题描述: 给定一个单链表,判断是否存在环。
求解思路:给两个速度不一样的指针,进入一个循环,查看二者是否相等。
算法代码:
bool Is_has_loop(link_list *head)
{ if(head == NULL)
return;
link_list *fast,*slow;
fast = slow = head;
while(fast && fast -> next)
{
fast = fast -> next -> next;
slow = slow -> next;
if(fast == slow)
{
break;
}
}
return !(fast == NULL || fast->next == NULL);
}
解法如下:
定义两个指针:fast和slow,当fast按照每次2步,slow每次一步的方式走,发现fast和slow重合,确定了单向链表有环路了。
二、求环的入口
接下来,让fast回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当fast和slow再次相遇的时候,就是环路的入口了。
这点可以证明的:
在fast和lslow第一次相遇的时候,假定slow走了n步骤,环路的入口是在p步的时候经过的,那么有
slow走的路径:
fast走的路径:
显然,如果从p+c点开始,p1再走n步骤的话,还可以回到p+c这个点
同时fast从头开始走的话,经过n步,也会达到p+c这点
显然在这个步骤当中slow和fast只有前p步骤走的路径不同,所以当slow和slow再次重合的时候,必然是在链表的环路入口点上。
找到环的入口代码实现:
link_list * FindLoopPort(link_list * head)
{
link_list * slow = head, * fast = head;
while ( fast && fast -> next )
{
slow = slow -> next;
fast = fast -> next -> next;
if ( slow == fast ) break ;
}
if (fast == NULL || fast -> next == NULL)
return NULL;
fast = head;
while (slow != fast)
{
slow = slow -> next;
fast = fast -> next;
}
return slow;
}