先用双指针探到是不是有回环,假设环长为D,head到环的距离(即要找的点到head的距离)为L,慢指针走的距离为L+X,快指针比慢指针快了一个或者多个环,所以为2*(L+X),注意X < D,因为快指针比慢指针多走了一个或者多个环,所以L+X = k*D。这样解得X = k*D - L。这时离环头点距离为D-X = (1-k)*D+L。再来个节点从head开始走,都是慢指针,这样俩个指针会在环头处相遇。因为在环里的那个指针走过的距离为L,这样离环头点距离为L-(1-k)*D+L = (k-1)*D % D = 0。就是环头点。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode *detectCycle(ListNode *head) { 12 ListNode *p, *q; 13 p = q = head; 14 if (!head || !head->next) return NULL; 15 while (q && q->next) { 16 p = p->next; 17 q = q->next->next; 18 if (p == q) break; 19 } 20 if (p != q) return NULL; 21 p = head; 22 while (p != q) { 23 p = p->next; 24 q = q->next; 25 } 26 return p; 27 } 28 };
C#
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * public int val; 5 * public ListNode next; 6 * public ListNode(int x) { 7 * val = x; 8 * next = null; 9 * } 10 * } 11 */ 12 public class Solution { 13 public ListNode DetectCycle(ListNode head) { 14 ListNode p = head, q = head; 15 if (head == null || head.next == null) return null; 16 while (q != null && q.next != null) { 17 p = p.next; 18 q = q.next.next; 19 if (p == q) break; 20 } 21 if (p != q) return null; 22 p = head; 23 while (p != q) { 24 p = p.next; 25 q = q.next; 26 } 27 return p; 28 } 29 }