LeetCode 142. Linked List Cycle II
141的进阶版,不仅要判断是否存在cycle,还有找出cycle的起始节点。
首先如141所做,根据fast==slow判断是否存在cycle。
如果fast==slow,则slow重置为head,此时fast和slow都每次走一步,当两者相遇时,相遇点即为圆环开头。现在证明为什么slow重置为head后可以一次走到圆环起点。
设非圆环部分有i个节点(不包括和圆环的交点),圆环有j个节点(包括和非圆环的交点)。首先在检测是否存在圆环部分里面,i次循环后,slow到了交点处,位置为i,而此时fast走过了2i个节点(即fast之前有2i个节点),fast在整个链表中位置为2i。现在设交点在圆环中的位置为0,所以slow在圆环中的位置为0,而fast之前的(包括交点这个节点)圆环节点有2i-i=i个,因此fast在圆环中的位置为i。像在141中的解释中一样,x=0,y=i,这样一来解得n=(c-a)j-i,b=x+n-aj=(c-2a)j-i。b为fast的圆环位置,现在slow重置为head,i次后slow到达交点处,而fast的位置为b+i,也就是(c-2a)j,即(c-2a)j%j,等于0,就是交点处。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode *detectCycle(ListNode *head) { 12 ListNode* slow = head, * fast = head; 13 while(fast && fast->next && fast->next->next){ 14 slow = slow->next; 15 fast = fast->next->next; 16 if(slow == fast){//cycle exists 17 slow = head; 18 while(slow != fast){ 19 slow = slow->next; 20 fast = fast->next; 21 } 22 return fast; 23 } 24 } 25 26 return NULL; 27 } 28 };