leetcode(List)–面试题 02.08. 环路检测
1,题目:
2,思路:
快慢指针:
思路:有俩个指针 fast ,slow分别的从起点a 开始走,slow走一步,fast走里俩步。如果过程中 快fast走到null,说明不存在环。否则fast和slow一定会相遇,相遇后,slow待在原地不动,将 fast放回原点。然后俩个指针每次都走一步,每次都走一步,每次都走一步。当俩个指针相遇的时候,就是环的入口。
证明:如上图所示,a是起点,b是环的入口,c是俩个指针相遇点,ab之间距离为x,bc之间距离是 y。
当slow 走到 b 时,由于fast 比 slow 走的快,所以fast 已经从 b 开始在环上走了 x 步,可能是多余一圈,距离 b 还差 y 步(解释:我们知道俩个指针相遇的点在c,我们让 slow 退回到b,fast 则会退回 2y 步,所以就是距离b 还差y 步,不会可以画图模拟一下)。知道了 fast 距离 b 还差 y 步,上面知道了 fast 从 b 开始在环上走了 x步。所以环的长度为 x+y。所以当俩个指针相遇时,把 fast 放回原点,slow 在 c点不动。然后每次都走一步,下一次相遇的时候就是b 点环的入口。
(以上可以结合图来理解,就可以理解了。)
下面的代码是来证明上述的结论。
3,代码:
快慢指针:
public class Solution {
public ListNode detectCycle(ListNode head) {
/*
有俩个指针 fast ,slow分别的从起点a 开始走,slow走一步,fast走里俩步。如果过程中 快fast走到null,说明不存在环。否则fast和slow一定会相遇,相遇后,slow待在原地不动,将 fast放回原点。然后俩个指针每次都走一步,每次都走一步,每次都走一步。当俩个指针相遇的时候,就是环的入口。
*/
if(head==null||head.next==null){
return null;
}
ListNode fast=head;//快慢指针都指向开头节点
ListNode slow=head;
while (fast!=null&&slow!=null){
fast=fast.next;
slow=slow.next;
if(fast!=null)
fast=fast.next;//快指针每次走两步,慢指针每次走一步
else
return null;//如果快指针为空,则证明不会相遇
if(fast==slow){//如果相遇了,从头开始
//如果相遇了,fast放回原点,slow待在原地不动,接下来是fast和slow每次都是走一步。当fast=slow的时候,就走到了环的入口
fast=head;
while (fast!=slow){
fast=fast.next;
slow=slow.next;
}
return slow;
}
}
return null;
}
}