如何确定一个链表中有闭环,如果有怎么确定起始点?

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

其次的一个思路就是联想生活中的知识了,两个人追着跑,如果有圈的话一定会相遇的.那么我们可以利用两个指针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相遇。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值