第一种方法是从单链表head开始,每遍历一个,就把那个node放在hashset里,走到下一个的时候,把该node放在hashset里查找,如果有相同的,就表示有环,如果走到单链表最后一个node,在hashset里都没有重复的node,就表示没有环。 这种方法需要O(n)的空间和时间。
第二种方法是设置两个指针指向单链表的head, 然后开始遍历,第一个指针走一步,第二个指针走两步,如果没有环,它们会直接走到底,如果有环,这两个指针一定会相遇。方法二的实现代码如下,程序中找出了环的起始位置:
node* first_loop_port(node *head)
{
node *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;
slow = head;
while (slow != fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
这里用到了一个巧妙的处理方法:
假设环长为L,起始点到环入口长度为a,环长度为r,设慢指针和快指针相遇前,慢指针在环内走了x步(快指针已经走了n圈),同时假设慢指针已经走了s步,则快指针走了2s步。
则有:2S = S + n r ;则s = nr;
又 a + X = S;故a+X = nr = (n-1)r+r = (n-1)r + L-a;则a = (n-1)r + L-a-X;含义为环入口距离起点的距离和相遇点距离环入口点的距离相等。
故让慢指针回到起点,快指针从相遇点开始继续走,当两者相等时,则为环入口地址。
【转自http://blog.youkuaiyun.com/yushuai007008/article/details/7644954】