题目
思路
用一个每次走两步的快指针和一个每次走一步的慢指针
如果fast会是null,那就说明链表没有环
如果是有环的话,1. 先让fast和slow相遇,2. 然后slow保持在相遇的位置,fast回到head。他们再次相遇的时候就是起始节点。原理如下:
- 当fast和slow相遇的时候,fast走的是slow的两倍
- 当fast和slow相遇时,fast多走的k步一定是在环里绕圈。
- 从环起点到相遇点距离为m,那么从slow走的距离来分析,从head到环起点是k - m
- 那么对于fast,多走的距离是绿色的圆圈,减去m后正好y也是k - m
- 让slow从相遇点开始走,fast也回到head一步一步走,那两个指针会在初始点相遇
代码
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var detectCycle = function(head) {
if(head == null || head.next == null) return null;
//快慢指针
//这里必须先走起来,如果让fast和slow都指到head上,while(fast != slow)就会直接跳过
let fast = head.next.next;
let slow = head.next;
while(fast != slow){
if(fast == null || fast.next == null) return null;
fast = fast.next.next;
slow = slow.next;
}
//此时slow和fast停在同一个位置,且必有环
fast = head;
while(fast!== slow){
fast = fast.next;
slow = slow.next;
}
return fast;
};