首先快慢指针是指 两个指针移动速度不一样,比如 fast 指针每次移动长度为2,slow 指针每次移动长度为 1 ,这样如果链表中存在环的话,fast 指针和 slow 指针一定会相遇
快慢指针可以解决什么问题?
- 判断链表是否有环
- 寻找链表的中点,(fast指针走到终点的时候,slow走到中点)
- 寻找链表的倒数第k个节点 (设 fast = slow + k,fast 走到链表末尾时,slow走到倒数第k个节点)
- 寻找链表的入环点 (先得到相遇指针,在让慢指针与相遇指针一起走,相遇的点就是入环点)
- 求有环链表的环长 (第一次相遇后,让快慢指针继续跑,第二次相遇时,两者步数之差就为环长)
寻找链表的入环点
如图所示,如果链表中存在环,fast 指针和 slow 指针一定在环中相遇 这时 fast 指针走过的距离为: slow 指针走过的距离为:由于 slow 指针走一步,fast 指针走 两步,所以 即: 化简得到:
等式成立的条件是:
(y + z)代表走一圈的距离
所以让 fast 指针和 slow 指针相交处的指针,绕环移动 那么这个指针走到入环点的距离是 所以相遇指针和指向头节点的指针,同时开始移动,必然会在入环点相遇。
fast 指针每次移动 3 步是否可行? 4步,5步呢?
设 fast 指针每次走 k 步,环的长度为 s,并且 fast 指针和 slow 指针在第 n 圈的时候相遇,相遇点为 y
那么得到等式 化简得: 将(y + z)除过去,得:
其中 x,s 是确定的,变量 步长 k 和 相遇点 y ,和 圈数 n
........
证不出来,希望有那位佬可以帮忙从数学式子的角度证明一下
上另外一种好理解的证明方法:
假设,慢指针步长为 1,快指针步长为 k,环入口到链表起点距离为 x,环的长度为 s.
因为慢指针是一步一步走,所以可以遍历到链表中的每一个点,所以我们可以假设他们会相遇再任意一个节点
设 快慢指针 相遇点为 y 且 y 为 s 的整数倍,且 y > x; 那么 y 就表示 选取快慢指针相交的点。
那么此时快指针走过的距离为 ky,快慢指针的路径差为 (k - 1) * y; 因为 y 是 s 的整数倍,所以快慢指针肯定能遇见。
根据上面的假设有式子:(k - 1)y = (k - 1)ns,s是确定的,n可以取满足 y 大于 x 的最小值,所以k - 1越小,相遇的越快,当 k = 2 时,有最小值
题目打卡
下面四道题中,前面两道可以用双指针来做,后面两道可以用快慢指针来做。