快慢指针判断链表是否有环

关于链表是否有环,其实是一系列问题,主要包括以下几个:

 

1.判断单链表是否有环:

使用快慢指针fast和slow,fast每次走两步,slow每次走一步,如果有环,肯定会相遇,如果没有,则指针fast遇到NULL退出。追及相遇问题。

2.求有环单链表的环长

在环上相遇后,记录第一次相遇点为Pos,之后指针slow继续每次走1步,fast每次走2步。在下次相遇的时候fast比slow正好又多走了一圈,也就是多走的距离等于环长。

设从第一次相遇到第二次相遇,设slow走了len步,则fast走了2*len步,相遇时多走了一圈:

    环长=2*len-len

3.求有环单链表的环连接点位置

 

 

  第一次碰撞点Pos到连接点Join的距离=头指针到连接点Join的距离,因此,分别从第一次碰撞点Pos、头指针head开始走,相遇的那个点就是连接点。在环上相遇后,记录第一次相遇点为Pos,连接点为Join,假设头结点到连接点的长度为LenA,连接点到第一次相遇点的长度为x,环长为R

    第一次相遇时,slow走的长度 S = LenA + x;

    第一次相遇时,fast走的长度 2S = LenA + n*x;

    所以可以知道,LenA + x =  n*R;  LenA = n*R -x;

4.求有环单链表的链表长

   上述2中求出了环的长度;3中求出了连接点的位置,就可以求出头结点到连接点的长度。两者相加就是链表的长度。

5.如果快指针每次走三步,四步,五步...会怎么样?

  不管快指针走多少步,只要有环就会与慢指针相遇,因为慢指针每次都走一步。但是如果快指针每次走三步以上,就会导致上述公式不成立。比如说快指针每次走三步,则公式变为:

    第一次相遇时,slow走的长度 S = LenA + x;

    第一次相遇时,fast走的长度 3*S = LenA + n*x;

    所以可以知道,2*LenA + 2*x =  n*R;  LenA = n*R/2 -x;

举例:头结点之后就是环的入口,环除了入口还有一个节点,fast每次走三步,slow每次走一步,第一次会在环的入口相遇,分别从第一次碰撞点Pos、头指针head开始走,无法相遇。

 

参考文献:

https://www.cnblogs.com/xudong-bupt/p/3667729.html

 

posted @ 2018-10-09 20:38  代码喵在进步  阅读(3876)  评论(0编辑  收藏  举报