结论:
想必大家知道找这种节点结论都是:让指针从链表起始位置出发,同时让一个指针从相遇点出发,各走一步,最后会在环的第一个节点相遇。接下来我就从自己的角度展开说说这个结论。
一相遇条件:
首先是什么时候才会相遇呢,结论的这个相遇点是怎样的快慢指针组合得出的?我们都知道如果快指针走两步,慢指针走一步,只要存在环就最终一定会追上,但是如果快指针走三步,慢指针走一步,这个时候还能追上吗?我们来推导一下,
我们假设链表存在环,环的周长C,头节点h到入环的第一个节点E距离为L,当慢指针走到E点,假设此时快指针走到M点,快指针要追击距离为x, 快指针相对慢指针每次走两步,那这个x就会每次减2,如果x是奇数,这个x的变化应该是x-2,x-4.....3, 1, -1,这个-1是什么意思呢?我当时也有点疑问了,那中间有没有相遇呢,好像有,其实没有相遇,我之前把它混淆为初高中物理的相遇问题了,错误地以为有相遇,在这里我们一定要注意:当快慢指针相差一步的时候,下一次,快指针就走到了慢指针的前面,但快指针只是从慢指针旁边路过,不是相遇。好了这个时候距离变成-1,实际上两者距离是圆的周长C-1,之后就还是快指针的追击了,如果R-1是偶数,最后一定会相遇,如果是奇数,比如7, 那每次距离变为5,3,1,又回到-1那么最后就是永远也不会相遇。
当然如果快指针是走四步,慢指针走一步,是否会相遇这个点深究下去就有些偏了,而且展开说也挺多情况,我们末尾再讨论。
二推导公式论证结论:
我们也就可以接着讨论第二步:计算相遇时走过的距离,当然我们是计算快指针走两步,慢指针走一步最终相遇走过的距离,此时我们假设链表存在环,环的周长R,头节点h到入环的第一个节点E距离为L,设A为相遇点,(读者注意分清,两次假设不一样)当慢指针走到E点,快指针不知道到哪了,但是我们很清楚慢指针一定是在第一圈就被追上,慢指针不会有走到第二圈的机会,追击距离最远就是R-1,此时慢指针走R-1步就会被追上,当追击距离为R,此时快指针套圈慢指针,已经是相遇了,
所以慢指针最终走的距离就是L+X,那快指针呢?我们无法确定快指针是在第几次到达A点和慢指针相遇,但是我们明确知道的是,快指针第一次到达A点的时候,二者没有相遇,慢指针此时还在快指针后面呢,所以快指针到达相遇点的走过的总距离是L+X+nR, 而L+X+nR=(L+X)*2,解得L=nR-x=(n-1)R+R-x; 表明在环内L的长度是等价于R-X,所以也就证明了结论使得一指针从相遇点出发,一指针从头节点出发,每次各走一步,最终会在入环口处相遇。
那如果这个相遇点时快指针走三步,慢指针走一步得出的呢?首先两指针走过的距离分别还是L+X+nR和L+X,只是等号两端成立条件变为3倍,L+X+nR=(L+X)*3,解得L=R-X+(n-2)*R/2,此时已经很难和结论契合了,只有当n满足(n-2)/2是个整数才能同样得出结论:在环内L的长度是等价于R-X,才可以找链表起始点,还有大家可千万别忘了这种指针相遇还有前提条件(一开始的追击距离对某个数取模要为零),所以当我们要找链表环的头节点要找相遇点最好选用快指针走两步,慢指针走一步的相遇点,更具普适性。
补充:快指针是走四步,慢指针走一步,相遇问题拓展
之所以放到后面才说主要是这已经偏离我要证明的结论,为了怕太多情况讨论使得大家厌烦所以放到后面。我们假设链表存在环,环的周长C,头节点h到入环的第一个节点E距离为L,当慢指针走到E点,假设此时快指针走到M点,快指针要追击距离为x, 快指针相对慢指针每次走三步,
那这个追击距离如果是3的倍数,那最终能相遇,如果不是三的倍数会出现什么情况呢?其实就是对X取模的结果分析,我们画图来看看。显然只会出现剩余1和2的情况,此时追击距离变成c-1和c-2,此时假设c大于等于3。
我在分类讨论C-1和C-2是否是三的倍数时发现C,C-1和C-2是个连续的三个整数,当C是三的倍数时,你会发现追击距离会在C-1和C-2永远循环下去,当C-1是三的倍数时,那说明C-2就绝对不可能是三的倍数,但是C-2在不断减三的过程中,最后是剩下个2,再减三变成C-1,此时就能追上了。
如果C-2是3的倍数,那C-1就绝对不可能是三的倍数,但是C-1最后剩下的数字是1,再减三变成C-2,此时就也可以追上了。 还有就是极端情况当c小于3,如果一开始追击距离X取模3不为零,那就只能为1或者2,如果周长C取得又是1,2这两个数,当C是1的时候,其实这个周长为1的环我认为应该是应该节点自己指向自己,这个时候无论怎样都一定能追上,当C是2的时候,追击距离是1时,我认为这种情况下(快指针走三步,慢指针走一步)永远追不上,当然追击距离是零就不用追了。