- 设置两个指针一个快指针每次走两步(
fast->next->next
),一个慢指针一次走一步(low->next
)。 - 如果链表中没有环它们最后肯定不相遇,反之它们一定会在环中相遇。
- 如上图链表中有环,从x点出发,环的入口为点y,它们最后会在z点相遇。
- 设x到y长度为a,y到z的长度为b,z到y的长度为c,快指针在环中绕了k圈,在k+1圈与慢指针相遇。
- 慢指针走了a + b的长度,快指针走了 a + k(b + c) + b ,
因为快指针每次走的是慢指针的两倍。
则 2*(a + b)= a + k(b + c) + b 。
化简 得 a = (k-1)(b + c) + c。 - 即x到y的长度 = k-1圈环的长度 + z到y的长度。即当一个指针从头x开始走,另一个指针从相遇点z开始走,当它们相遇时候一定是在环的入口y。
/** 2*(a + b) = a + k*(b+c) + b a = (k-1)*(b +c) +c 当指针从头开始,走到环的入口刚好等于另一个指针从相遇位置走(k-1)圈 到达 环入口 */ class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *fast,*low; low = fast = head; bool noRing = true; // 是否存在环 while(fast && fast->next){ // NULL->next 会报错 low = low->next; fast = fast->next->next; if(low == fast) { noRing = false; // 有环 break; } } if(noRing) return NULL; // 没有环 返回 fast = head; while( fast != low){ fast = fast->next; low = low->next; } return fast; } };