这个问题很有趣,首先我第一个直觉是用图论的知识来解决,但是这是不可行的.因为我们没有办法将每一个节点的信息保存起来(这样的代价过于巨大,每一个节点标志唯一的就是它本身的地址,但是地址这个信息不能直接映射为容器的下标,它的值过于巨大,所以很难存储).

其次的一个思路就是联想生活中的知识了,两个人追着跑,如果有圈的话一定会相遇的.那么我们可以利用两个指针p1,p2(每次分别增1和2)来进行判断.这里又有一个问题怎么确定终止的条件呢?如果这个链表特别长怎么办?

[1]首先一个终止的条件是指针p2遇到NULL节点.这说明不存在闭环.
[2]另外一个条件式当两个指针相遇就终止,这说明有闭环.链表有可能是这样的形式(环在起始点很容易判断,不讨论):
{....................这一段直路径记作x...........}
----------------------------------------------
##                                            |
##                                  ----------|(环的起始点,环的周长记作c)                               |         |
##                                  |         |
##                                  |         |
##                                  |         |
##                                  -----------
现在判断怎么获得环的起始点,我们记下第一次相遇的节点,作为t1,很显然,当p1刚到环起始点时,它走了x.p2走了2x,我们假设它距离环的起始点位x%c,将该位置记作t0(注意,不是x,因为x可能远大于c,p2可能已经跑了环几圈了,x = nc + x%c).这样p2要追上p1就需要多走c-x%c的距离,那么p1就会走这么多的距离,所以第一次相遇的地方就是距离环起始点还有x%c的位置了(这个t1与t0关于环的起始点对称,都距离起始点x%c)。现在只需要从起始点在出发一个指针p3,它以步长1自增,走到环起始点时走了x,那么p1也走了x,它将会回到原点,恰好和p3相遇。
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐