https://oj.leetcode.com/problems/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?
解题思路:
这是个比较复杂的题目,用快慢指针的方法,可以比较容易的得到链表是否有环,但是他俩第一次相遇的node,并不一定是环开始的节点。那么,如何求解?
考虑上面的链表,环前的长度为X,环长Y,fast和slow相遇时,已经在环里走了K。假设这时fast绕了m圈,slow绕了n圈,走了T个回合。于是有,
fast:2T=X+Y*M+K
slow:T = X+Y*N+K
消除T,2X+2YN+2K = X+YM+K,于是,X+K=(M-2N)*Y。
这时一个重要的等式,说明X和K相加,必然等于Y的正数倍。也就是说,fast和slow在K相遇时,再一步一步的走X步,肯定回到环的起点了。当然,这时可能只绕了一圈,也可能绕了很多圈(X很长时)。
于是,我们只要仿照判断是否有环的方法,循环直到fast和slow相遇。然后将fast放到head,fast一步一步走X步,到了环的起点,slow也一定到环的起点了。
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode detectCycle(ListNode head) { if(head == null){ return null; } ListNode fastNode = head; ListNode slowNode = head; do{ fastNode = fastNode.next; if(fastNode == null){ return null; }else{ fastNode = fastNode.next; } slowNode = slowNode.next; }while(fastNode != slowNode && fastNode != null); if(fastNode == null){ return null; } fastNode = head; while(fastNode != slowNode){ fastNode = fastNode.next; slowNode = slowNode.next; } return fastNode; } }
这是一个根据网友总结写出的算法,参考了以下几个页面。
http://fisherlei.blogspot.jp/2013/11/leetcode-linked-list-cycle-ii-solution.html
http://www.cnblogs.com/hiddenfox/p/3408931.html