LeetCode: Linked List Cycle II 解题报告
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:
1. 先用快慢指针判断是不是存在环。
2. 再把slow放回Start处,一起移动,直到二个节点相遇,就是交点。
现在有两个指针,第一个指针,每走一次走一步,第二个指针每走一次走两步,如果他们走了t次之后相遇在K点
那么 指针一 走的路是 t = X + nY + K ①
指针二 走的路是 2t = X + mY+ K ② m,n为未知数
把等式一代入到等式二中, 有
2X + 2nY + 2K = X + mY+ K
X + (2n-m)Y + K = 0;
X + K = (m - 2n)Y
这就清晰了,X和K的关系是基于Y互补的。等于说,两个指针相遇以后,再往下走X步就回到Cycle的起点了。这就可以有O(n)的实现了。
Ref: http://fisherlei.blogspot.com/2013/11/leetcode-linked-list-cycle-ii-solution.html
解释2:
主页群自己也算了一下,给出另一个解释:
假设S,F两个指针首次相遇在Z点,SL, SF分别为两个指针走过的距离,则
SL = a + b
SF = a + b + nL (L 为环的周长)
=> 2(a + b) = a + b + nL
a + b = nL
a = nL - b = (n - 1)L + L - b = (n - 1) L + c
因为a + b > 0,所以nL > 0, n > 0, n >= 1 推出 n - 1 >= 0
所以,a的长度为c 加上 ML (M > 0)
就是当SLOW重新从原点出发,而FAST继续走时,当SLOW走到Y点,FAST也会绕N圈后再走C长度到达Y点,
两个点正好会在Y点相遇。
得证。
1 /** 2 * Definition for singly-linked list. 3 * class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode(int x) { 7 * val = x; 8 * next = null; 9 * } 10 * } 11 */ 12 public class Solution { 13 public ListNode detectCycle(ListNode head) { 14 if (head == null) { 15 return null; 16 } 17 18 ListNode s = head; 19 ListNode f = head; 20 21 ListNode cross = null; 22 23 while (f != null && f.next != null) { 24 s = s.next; 25 f = f.next.next; 26 27 if (s == f) { 28 cross = s; 29 30 // remember to break here, or you will get a loop. 31 break; 32 } 33 } 34 35 // don't detect any cycle. 36 if (cross == null) { 37 return null; 38 } 39 40 // place the slow to the start again. 41 s = head; 42 while (true) { 43 if (s == f) { 44 return s; 45 } 46 47 s = s.next; 48 f = f.next; 49 } 50 } 51 }
GITHUB:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/list/DetectCycle.java
posted on 2014-12-10 15:58 Yu's Garden 阅读(872) 评论(0) 编辑 收藏 举报