环形链表
题目描述
142. 环形链表 II - 力扣(LeetCode)
给定一个链表,返回链表入环的第一个节点。无环返回null。
解题思路
环形链表问题,通用的解法,是通过设置双指针,
1 | let runSlow = head |
将 runFast 的速度,设置为2,runSlow 的速度设置为 1,当 runFast 所在节点等于 runSlow 所在节点代表追上了。
因为 runFast 和 runSlow 同时出发,且 runFast 的速度为 runSlow 速度的两倍。
无论如何 runSlow 跑的第一圈就会被追上。
1 | while(runFast && runFast.next){ |
如果有环,到这里我们已经能够得到,runFast 和 runSlow 的相遇点了。
题解:
相遇时:
- runSlow 走距离为:R + Y;
- runFast 走的距离为:R + n(Y+S) + Y
- R + n(Y+S) + Y = 2(R + Y)
- (n-1)Y + nS = R
只要以上等式成立即可,可以任意取n,这里取n为1:R = S,
也就是入口点的距离等于相遇点到这一圈终点的距离。
这是我知道了 R=S 这个结论后,再推倒的,如果不知道结论,本弱还在设圈的周长的未知数呢。并且最后一步的思想很关键。任意取。
所以根据这个结论,我们从起始点再放一个速度为 1 的节点,并且让runSlow继续跑,和这个新节点相遇的点就是入口点,这里为了节省那一点点内存,可以让runFast受累一下,让他从新从head开始以1的速度跑。
1 | runFast = head |
知识积累
- 入口点的距离等于相遇点到这一圈终点的距离
- 不相关的参数可以任意设