*LeetCode--142. Linked List Cycle II (找出循环链表的循环头部)
问题大意:给定一个链表,找到链表循环部分的头部。如果不存在循环,返回null。
找链表头部的方法:
链表头是X,环的第一个节点是Y,slow和fast第一次的交点是Z。各段的长度分别是a,b,c,如图所示。环的长度是L。slow每次前进1个元素,fast每次前进两个元素。

首先给出判别链表是否有环的方法:使用两个指针slow,fast。两个指针都从表头开始走,slow每次走一步,fast每次走两步,如果fast遇到null,则说明没有环,返回false;如果slow==fast,说明有环,并且此时fast超了slow有n圈,返回true。
拓展:确定循环部分的长度: 在两个指针相交后,fast停止,slow继续向前,并且计数。当slow==fast时,即可得到循环部分的长度。
那么如何得到循环部分的头部?
slow走过的路程:a+b
fast走过的路程:a+b+n*(b+c)
由于fast的速度是slow的2倍,有 2*(a+b) = a+b+n*(b+c) 得到 a = n(b+c) - b;
a = c+(n-1)*(b+c) 即a的路程=c+(n-1)圈循环部分的路程
因此想要得到循环部分的开始,可以令一个指针从头部开始,另一个指针从z开始,每次移动1步,最终相交的位置就是循环头部。
public static ListNode detectCycle(ListNode head) { if (head == null) return null; ListNode p1 = head; ListNode p2 = head; do{ if (p1 != p2) { p1 = p1.next; p2 = p2.next.next; }else{ break; } } while(p2 != null && p2.next != null); System.out.println(p1.val+" "+p2.val); //首次相交的位置 if(p1==p2){ ListNode start = head; while(start!=p1){ System.out.println(start.val); start = start.next; p1 = p1.next; } return p1; } return null; }

浙公网安备 33010602011771号