[分析] 这题可以说是快慢指针的经典题。首先判断是否存在环,而后找寻环的入口点。自己的naive思路是从快慢指针相交点处将链表分割成两个新链表,两个新链表的第一个交点即为环的入口点。更优化的思路是参考来的方法2,比较巧妙,但自己总是记不住,明明也理解了……优化法解析参考 http://blog.csdn.net/kenden23/article/details/13871699
public class Solution { // method 2 public ListNode detectCycle(ListNode head) { ListNode slow = head, fast = head; while (fast != null) { fast = fast.next; if (fast != null) { slow = slow.next; fast = fast.next; if (slow == fast) break; } else { return null; } } if (fast == null) return null; slow = head; while (slow != fast) { slow = slow.next; fast = fast.next; } return slow; } // method 1 public ListNode detectCycle1(ListNode head) { ListNode slow = head, fast = head; // step1: check if there is cycle while (fast != null) { fast = fast.next; if (fast != null) { slow = slow.next; fast = fast.next; if (slow == fast) break; } else { return null; } } if (fast == null) return null; // step2: find the node which the cycle begins // split list at the meet node of slow and fast & search the first same node of the two list ListNode head2 = fast.next; fast.next = null; int len1 = 0, len2 = 0; ListNode p = head, q = head2; while (p != null) { p = p.next; len1++; } while (q != null) { q = q.next; len2++; } int diff = Math.abs(len1 - len2); p = head; q = head2; if (len1 > len2) { for (int i = 0; i < diff; i++) p = p.next; } else if (len1 < len2) { for (int i = 0; i < diff; i++) q = q.next; } while (p.val != q.val) { p = p.next; q = q.next; } fast.next = head2; return p; } }