Linked List Cycle ii
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Follow up:
Can you solve it without using extra space?
SOLUTION 1:
最开始的想法和 Linked List Cycle这一题一样。
SOLUTION 2:
同样是两个指针,一快一慢,相遇时跳出循环,只要循环结束时fast不为空,即有环。
(fast != NULL && fast->next != NULL)或者(fast != slow)
显然后一种写比较简洁。
然后让链表头和slow一起按照相同速度移动,相遇的点就是环开始的地方。
设链表头到两个指针相遇的地方长度为 A, 环的长度是 B.
相遇的时候,
slow的路程 Ls = A + k1*B; (k1 = 0,1,2...)
fast的路程 Lf = A + k2*B; (k2 = 1,2,3... k1<k2)
fast速度是slow的2倍 2*Ls = Lf;
Lf - Ls = (k2-k1)*B = Ls = A + k1*B;
即 A = (k2-2*k1)*B
设两个指针相遇的地方距离环的头是x;
则 A-x = (k2-2*k1)*B
而slow提前了x步。
1 ListNode *detectCycle(ListNode *head) { 2 if(head == NULL || head->next == NULL) 3 return NULL; 4 ListNode *slow = head->next; 5 ListNode *fast = head->next->next; 6 while(fast && fast->next){ 7 if(slow == fast) 8 break; 9 slow = slow->next; 10 fast = fast->next->next; 11 } 12 // if(fast != NULL && fast->next->next != NULL) is OK too. 13 if(slow != fast) return NULL; 14 fast = head; 15 while(fast!= slow){ 16 fast= fast->next; 17 slow = slow->next; 18 } 19 return slow; 20 }
SOLUTION 3:
这种解法和第二种本质区别,只是这种做法将问题分解为1)是否有环 2)若有,则找两个链表的交点;若无,则返回NULL;
这样将问题就能联系到之前的find intersection的问题了。解法来自
1 public ListNode detectCycle(ListNode head) { 2 if (head == null) return head; 3 //first check whether cycle exists or not 4 ListNode first, second; 5 first = second = head; 6 while(true){ 7 first = first.next; 8 if (second.next != null) second = second.next; 9 else return null; 10 if (second.next != null) second = second.next; 11 else return null; 12 if (first == second) break;//list contains a cycle break 13 } 14 15 //cycle exists store the intersect node 16 ListNode intersect = first; 17 first = head; 18 int k = 1;//the distance of the intersect node from head 19 while(true){ 20 if (first == intersect) break; 21 first = first.next; 22 k++; 23 } 24 //这里找交点的方法如果用将两个链表形成环的办法,则解法与SOLUTION2相同 25 //the intersection is at distance k away from the head; 26 //now get the size of the loop 27 int s = 0;first = intersect; 28 while(true){ 29 first = first.next; 30 s++; 31 if (first == intersect) break; 32 } 33 //s is the size of the loop now 34 35 //now the question reduces to find the first intersecting element 36 //of two linked lists, list1 starts at head, list2 starts at intersect now 37 38 //the first step is to align the nodes so they are at the same distance from the end(intersect node) 39 first = head;second = intersect; 40 if (s > k){ 41 for(int i = s; i < k;i++) 42 second = second.next; 43 }else{ 44 for(int j = k; j < s; j++) 45 first = first.next; 46 } 47 while(true){ 48 if (first == second) return first; 49 first = first.next; 50 second = second.next; 51 } 52 }