您的位置:首页 > 理论基础 > 数据结构算法

判断链表是否有环

2016-06-21 10:47 344 查看
问题:

1.如何判断是否有环?如果有两个头结点指针,一个走的快,一个走的慢,那么若干步以后,快的指针总会超过慢的指针一圈。

2.如何计算环的长度?第一次相遇(超一圈)时开始计数,第二次相遇时停止计数。

3.如何判断环的入口点:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。

为什么呢?需要一个简单的计算过程:

(1)当fast与slow相遇时,slow肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步(至少是2s步,因为是离散的,fast至少比slow快一倍,换句话说slow走一步,fast至少走2步)。fast的步数还等于s走的加上环里转的n圈,所以有:2s = s + nr。因此,s = nr。

(2)设整个链表长为L,入口距相遇点X,起点到入口的距离为a。因为slow指针并没有走完一圈,所以:a + x = s,带入第一步的结果,有:a + x = nr = (n-1)r + r = (n-1)r + L - a;即:a = (n-1)r + L -a -x;

这说明:从头结点到入口的距离,等于转了(n-1)圈以后,相遇点到入口的距离(X为入口到相遇点,L-a-X为其补距离)。因此,我们可以在链表头、相遇点各设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。个人理解:此时,从头结点走到入口点P1,走了a,此时,从相遇点走的P2,走了(n-1)r+X的补距离,因此,也到达入口点,所以此时是第一个入口点,也是二者的第一次相遇点。

也许大家有一个问题,就是为什么“当fast与slow相遇时,show肯定没有走完链表”。这个问题比较坑,我也没有找到很好的证明。不过大家自己画几个试试,会发现的确是这样。

个人理解:fast至少比slow快一倍,上面已解释,那么假设二者均从入口点走,那么第一次相遇必然在入口点,此时slow走了一整圈,如果从头结点开始走,fast进入环时,slow还未进入环,fast开始走环,假设走了一个格子,此时slow进入,那么当slow走了一圈时,fast已经超过slow至少一圈+一个格子,此时相遇过了,说明,相遇必然在slow走完一圈之前。





首先要明确一点,链表是内存上的结构,如果某一节点相同了,那么后学的必然相同。

4.如何判断两个链表(不带环)是否相交?

首先:将2个链表一起走到最后一个节点(不是结束),比较二者是否相同,相同则说明相交,否则不相交。假设链表1的长度为L1,链表2的长度为L2,如果L1大,那么L1先走L1-L2个长度,否则L2先走L2-L1个长度。接下来一起走,第一个相交的节点即相交点。





5.如何判断两个有环链表是否相交?

设环的入口点分别为Loop1和Loop2.如果2者相等,那么需要考虑的就和前面无环类似,只不过中点是Loop1(Loop2)



如果不等,分为2种情况,独立的2个环或者一个大环。

独立的2个环,将Loop1走一圈,碰不到Loop2,那么不相交,大环,碰到了Loop2,那么返回Loop1或Loop2均可。







6.一个链表有环一个链表无环肯定是不会相交的。因为相交必然从后面开始,一个有环进入了环,另一个无环,进入不了环,所以肯定不相交
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  链接 相交 数据结构