142. Linked List Cycle II

  不定期更新leetcode解题java答案。

  采用pick one的方式选择题目。

  题意为给定单链表,如果链表存在循环回路则返回进入循环的开始节点,否则返回null。

  易想到采用双指针的方式来判断是否单链表存在循环回路,具体方法是:将两个指针赋值为链表头,以不同速度向后遍历,如果两者可以相等,则有循环;否则为快速指针先进行到链表尾,不存在循环。

  本题另外一点在于如何能找到循环回路的开始节点。试想假如存在回路,则满足如下关系:

  m + n = l && m + n +s * k = 2 * l

  上述式子的意义为:两个指针一个用单倍速度向后遍历,一个用双倍速度向后遍历,两者最后相遇在一起。m为进入循环前经过的节点数,n为进入循环后经过的节点数,l为慢速指针经过的总节点数,k为循环回路一个循环的节点数,s为正整数(未知)。

  换句话说就是将两个指针的路程用我们可以添加的未知量加入进去。我们要得出的是m这个未知数,以通过链表头获取循环回路开始节点。

  通过观察可得出: m + n + m = l + m = s * k + m

  很显然,由两个指针节点相遇处再前进m个节点即可到达循环回路开始节点(总路程为m+s圈循环),而该点恰好为从链表头前进m个节点的位置。由此可以将快慢指针相遇处与链表头两个节点同时同速度向后遍历,相遇处即为所求。具体代码如下:

 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         ListNode slow = head, fast = head;
15         int count = 0;
16         while(fast != null && fast.next != null){
17             count++;
18             slow = slow.next;
19             fast = fast.next.next;
20             if(slow == fast)
21                 break;
22         }
23         if(fast == null || fast.next == null)
24             return null;
25         
26         slow = head;
27         for(int i = 0; i <= count; i++){
28             if(slow == fast)
29                 break;
30             fast = fast.next;
31             slow = slow.next;
32         }
33         return slow;
34     }
35 }

 

posted @ 2016-10-26 14:16  zslhq~  阅读(158)  评论(0编辑  收藏  举报