PHP判断链表是否有环,判断单链表是否有环、求环长和环入口最优算法

判断单链表是否有环是一个十分经典的算法问题,许多考试或者面试都有很大的几率出现。如果事先对此没有一定的理解,临场发挥可能就比较困难了。

判断链表是否有环

首先定义两个指针 slow 和 fast,初始都指向链表头指针 head;

然后,slow 每走一步(每次移动一个节点),fast 走两步(移动两个节点);

如果 fast 遇到了 NULL,则链表不存在环;

如果 slow==fast,则链表存在环;

1886

为什么 slow==fast 就一定会存在环呢?

因为,如果存在环,fast 和 slow 肯定会先后进入环;

当 slow 刚好进入环时,fast 肯定已经在环内的某一个位置了;

而又因 fast 走的速度是 slow 的两倍,所以在 slow 在环内遍历一遍的过程中,fast 指针必然会与 slow 相遇。

其实两个指针就像是两个人在田径场上跑步,一个人的速度是另一个人速度的两倍。无论两个人的起点在何处,慢的人跑完一圈,快的人必然跑完两圈,所以他们必然相遇过。

设链表长度为 n,显然时间复杂度为 O(n);

空间复杂度为 O(1)。

求环的长度

上面已经可以判断出是否有环了,如果有环,那么环的长度又是多少呢?该怎么求?

这就很简单了,前面已经将环判断出来了,所找到的 slow 和 fast 相遇点必然是在环内的,记录该节点;

所以此时只需用一个指针 p 继续一步步遍历链表,并计数,直到指针 p 重新指向上面的相遇节点,此时计数的值就为环长了。

设链表长度为 n,环长为 r 。

如果是在知道一个环内节点的情况下,那么时间复杂度为 O(r),空间复杂度为 O(1);

如果是在不知道是否有环的情况下,那么时间复杂度为 O(n+r),空间复杂度为 O(1)。

求环的入口

前面已经判断出是否有环了,并求出了环的长度,此时求环的入口也变得很简单了。

定义两个指针 p 和 q,初始指向链表头指针 Head;

q 首先移动 r 个节点(r 为环的节点数),p 不动;

然后 p 和 q 一起每次移动一个节点;

直到 p==q,此时 p 和 q 指向的就是环的入口了;

这个应该很容易理解吧,q 比 p 先走了一个环的长度,所以当 p 刚好走到环的入口时,q 就刚刚好遍历了环一遍。

复杂度分析

设链表长度为 n,环长为 r 。

如果是在知道一个环长度的情况下,那么时间复杂度为 O(n),空间复杂度为 O(1);

如果是在不知道环长度的情况下,那么时间复杂度为 O(n+r+n)= O(n+r),空间复杂度为 O(1)。

求链表的长度

链表长度 = 头结点到环入口节点的长度 + 环长度

所以此时,只需用一个指针从头遍历链表节点并计数,求出头结点到环入口节点的长度即可。

TOMORROW 星辰 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权

转载请注明原文链接:判断单链表是否有环、求环长和环入口最优算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值