一、使用快慢指针判断单链表是否有环
1、使用一个指针遍历链表,如果链表无环,那么可以遍历到链表结束;如果链表有环,那么会陷入死循环。
2、指针在环上遍历,如果有一快一慢两个指针一起遍历,那么它们一定可以相遇(想象两个速度不同的人在操场上赛跑);快慢指针在无环链表上一定不会相遇,假设初始状态都指向节点0(初始状态不认为相遇)。
二、为什么快慢指针(Fast-Slow)在环上一定相遇
0、上面已经有了定性的判断,认为快慢指针会相遇,但是还需要更加严谨的推导。与两人赛跑不同的是,快慢指针的速度更加明确,快慢指针走过的位置更具有离散性。
1、设F的速度为2,S的速度为1,假设F和S都在环上(如果有环,它们最终一定会走到环上,因为单个指针的遍历一定会陷入死循环);
2、假设F在S的后面追赶S,总是可以这么认为,因为:
2.1、F和S都是朝相同的方向前进;
2.2、如果F和S已经相遇,那么不用讨论了,相遇了就表示问题已经求解了;
2.3、如果F和S不在一处,假设S不动,F一直往前走(F和S有相同的前进方向),那么F一定可以遇到S,所以可以说S在F的前方;
3、F如何可以追上S呢?因为F的速度比S快,那么应该可以追上。因为F和S走过的点是离散的,我们可以借助数学归纳法证明它们一定会相遇。
3.0、假设:F在S的背后追赶S,上面第2条已经论述了这种说法的合理性;
3.1、如果F在S的背后差1个点:那么下一次F和S正好相遇,因为F每次走2点,S走1点;
3.2、如果F在S的背后差2个点:那么下一次F和S相差1个点,因为F比S多走了1个点,于是变成了3.1的情况,所以最后它们会相遇;
3.3、如果F在S的背后差3个点,那么下一次F和S相差2个点,情况变成了3.2,所以它们也会相遇,如此推导,无论它们相差多少个点,总是可以相遇的;
3.4、假设环上的点数为x,那么F和S相差不会超过x,最多相差x-1个点,所以它们一定会相遇。
三、思路回顾
不要问是怎么想到这个解法的,我也是从别人那里学来的,只是自己再梳理了一下逻辑。首先,直接遍历环形链表会陷入死循环;其次,2个速度有差异的指针在环形轨道上赛跑,一定会相遇;最后,通过归纳法证明,一个速度为1,一个速度为2,它们确实会相遇。