[面试题] 判断一个单链表是否有环

题目:

已知一个单向链表的头指针是 Node* pHead,如何判断该单项链表是否有环路!


Note 1:

看了很多文章中都是直接说定义两个指针,一个每次走一步(PA),一个每次走两步(PB),看最终是否相遇(有环),或者有一个指针指向NULL(无环)。看完之后有点懵,不知道为什么这样就能解决问题。无奈之下只要先证明方法的可行性了。


证明:(反证法)

如果链表中没有环,则走每次两步的指针(PB)肯定会先指向NULL;

如果链表中有环,并且能相遇(很显然一定在环中相遇),设在进入环之前有m个节点,环中有n个节点,PA在走x步之后与PB相遇,很容易列出公式:

(x - m) % n = (2*x - m) % n,

也就是

(2*x - m) - (x - m) = k * n (k为某一常数) 

化简得

x = k * n (k可以在保证k*n>m的情况下任意取值)

很显然该方程有解,所以如果有环肯定相遇。


Note 2:

虽然证明的结果表示方法是无误的,但是还是不能理解!悲剧.....

突然看到有人说这其实就是一个追击问题,我的思路一下子就打开了。

很显然,如果有环,肯定PB先进入环,那么PA进入环的时候有可能恰好与PB相遇(perfect,之后就不用说了),如果PA在进入环的时候没有与PB相遇,那说明PB到PA是有一定的距离的(相隔的节点数,设为N),那么PA每次走一步,PB每次走两步,也就是说PB每次想PA靠近距离1,那么只要在走N次,肯定相遇,到此豁然开朗!(对着答案分析都这么费劲,有点淡淡的忧桑~~~)


代码:

太简单了,就不写了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值