给定一个单向链表,判断有没有环,如果有环,求环开始的第一个节点。
这是一个比较tricky的问题,这里的环开始的第一个节点指的是非环节点之后的第一个能进入环的节点。
首先,我们可以通过p指针走1步和q指针走2步来发现链表有没有环。如果有环,那怎么能得到环的开始节点呢。
思考一下能发现,按照以上方法,最后发现有环的时候p和q指针一定指向了同一个节点。此时因为p一次走一步,q一次走2步,所以q走的步数是p的2倍。
如上图,如果假设链表头节点为A,要求的第一个环开始的节点为B,pq指针相遇时所指向的节点为C,那么此时p其实走过了线段AB+BC,而q指针走过了线段AB+(BC+CB)*n+BC,这里n指的是q在和p相遇前跑了这个环多少次。所以可以有方程:
2 *(AB+BC) = AB+(BC+CB)*n+ BC
化简后可得:AB = CB + (BC+CB)*(n-1)
即:AB = CB + L*(n-1)
这里L是环的长度。
尽管我们不能直接通过数学算出AB的值,但是我们仍然可以用计数的方法来count。我们令p重新指向头节点A,q指向C保持不变,接下来我们每次让p和q都往前前进一步。
假设此时p走到了节点B,显然p已经走过了AB长度,此时根据上面的等式q应该走过了CB + L*(n-1)长度,然而由于L*(n-1)只是绕环走了n-1次,所以当q走完L*(n-1)步后仍然回到了C点,等于没动过。此时q再走CB长度的话,必然q会指向B节点。
所以我们证明了当p和q相遇时其所指向的节点必然是我们要求的B。
(代码从略)
网友评论