判断一个单链表是否有环,若有,找出环的入口节点
分析:
一个单链表有环,必须是链表尾部带环;
(图片来自http://www.nowamagic.net/librarys/veda/detail/2245)
判断单链表是否有环,利用快慢指针的原理, 设置快慢指针 fast 、 slow 都指向单链表的头节点, 其中 fast 的移动速度是 slow 的2倍。
- 如果在fast==slow前,fast走到next==null结点,即没有环;
如果是有环的链表的话,当快慢指针(slow、fast)相遇时,slow指针肯定没有遍历完链表,而fast指针已经在环内循环了。
为什么会肯定的说,会在slow转第满一圈前的时候两指针必然相遇呢?
不妨设环长为L,第一个指针P1第一次进入环时,第二个指针P2在P1前方第a个结点处(0 < a < L);
设经过x次移动后两个指针相遇,那么应该有
0+x = (a + 2x) (mod L);
x =nL-a。(n=1,2,3….)
我们取第一次相遇,即n=1;所以有x=L-a.
下面这张图可以清晰地表明这种关系,
经过x = L-a次移动,P1向前移动了L-a个位置(相当于后退了a),到达P1′处,
而P2向前移动了2L-2a个位置(相当于后退了2a),到达P2′处,P1′和P2′相遇。
所以说,slow(P1) 在走步 x<圈长,后必然与fast相遇。
图片来自博客http://blog.csdn.net/loveyou426/article/details/7927297
也就是说,当在环里转圈时,如果A的速度是B的速度的2倍,A是肯定会追上B的,追上的点,就是开始时B位置 后面- 刚开始时A B距离;在A的第一圈,B的第二圈相遇。
参考:
http://blog.csdn.net/loveyou426/article/details/7927297
http://www.cnblogs.com/xiaodi914/p/5795096.html#commentform 介绍较具体
http://www.nowamagic.net/librarys/veda/detail/2245
http://www.2cto.com/kf/201603/493257.html 代码简单明了
指针p1从链表头、p2从相遇点,同时出发,一次移动一个节点,再次的相遇点便是环的入口点。
找入口原因:
http://blog.sina.com.cn/s/blog_6a0e04380101a9o2.html