还是快慢指针的问题, 当发现有环时,将fast指向head, fast一次向前移动一个节点, 则fast和slow一定会在环的入口相遇.
证明:
设S为slow指针走的节点个数, m为环的入口距head的位置
则第一次相遇时,fast和head相对于环入口的位置相同,
fast在环中的相对于环入口的位置在: (2S-m)%n
slow在环中的相对于环入口的位置在: (S-m)%n
(2S-m)%n = (S-m)%n, 则S%n==0
将fast放回到head位置, 改变速度为1, fast和slow都经过m个节点后
fast的位置(m-m)%n == 0, slow的位置(S+m-m)%n==0
fast和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) {
ListNode fast = head;
ListNode slow = head;
boolean ans = false;
ListNode ans_node = null;
while (true) {
if (fast == null)
break;
if (slow == null)
break;
if (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
} else {
break;
}
if (slow.next != null) {
slow = slow.next;
} else {
break;
}
if (fast == slow) {
//快指针和慢指针相遇, 一定有环, 下一步找出环的入口
fast = head;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
ans_node = fast;
break;
}
}
return ans_node;
}
}