【数据结构】带环链表

一、带环链表的判断

1.1 什么是带环链表

       如图所示,在单链表中,当其中一个节点不指向下一个而指向前的任意一个节点,使链表成环状。并且当我们遍历链表时,会陷入死循环。

1.2 如何判断是否为带环链表

      关于这个问题,我们首先要明确的是,在遍历中找到地址相同的节点(这里与相交链表的思路类似)。注意,不是找到数字相同的节点,不同节点可能储存相同的信息,而地址具有唯一指向性。

方法一:暴力遍历

     我们很容易想到的方法就是,创建一个数组,遍历这个链表,将链表各个节点的数据按顺序存入数组(每存入一个数a,就遍历一遍数组与数a进行比较,若相同,就),直至数组中有数字串循环出现。但是,这个方法时间复杂度达到了O(n!),空间复杂度为O(n),当数据过多时,非常影响运行速度。

这自然而然的就迫使我们找到更简单的方法。

方法二:快慢指针

    快慢指针,顾名思义就是设置一个每次走两步的快指针和一个每次走一步的慢指针,它是我们求解链表相关问题时常常使用的工具。

    两个指针同时从起始点出发,当快指针进入环时,慢指针才走到了入环路程的一半;当慢指针入环时,快指针可能已经在环中循环了好几圈。

在明确了这个问题之后,就是一个简单的追击问题。距离为C-X,速度差为1,相关代码如图所示:

知道了这些以后,我们不禁思考,当fast走两步slow走一步时,他们一定会相遇吗?如果回答是肯定的,那么当fast走n(n >= 3)步时还一定相遇吗?

二、快慢指针判断带环链表的证明

1.1 fast走两步,slow走一步

        假设slow进环的时候fast和slow之间的距离是N

        slow进环后,fast开始追击slow,slow每走一步,fast走两步,他们之间的距离每次缩小1。任何整数都是1的倍数,故当距离为0时就会相遇。

1.2 fast走x步(x>=3),slow走一步

        假设slow进环的时候fast和slow之间的距离是N
        当x = 3 时

        slow进环后,fast开始追击slow,slow每走一步,fast走三步,他们之间的距离每次缩小2。只有偶数才能整除2,故只有N为偶数时距离才会为0,才能相遇。N为奇数时距离永远不会为零,永远不会追上。

        当x 为4,5......时,能由上述推理轻易推出,都不能追上。

三、带环链表的环长以及入环点

3.1带环链表的环长

        从相遇点遍历一遍回到原点,就是环长。

3.2带环链表的入环点

                起始点—入环点距离:L;入环点—相遇点距离:X(0<= X < C);环的长度:C;

                slow走的距离:L+X;      fast走的距离:L+n*C+X;

              又fast走的距离为slow的两倍,有:2(L+X) = L+n*C+X;即 L = n*C - X = (n-1)*C + C - X;

由上述推理可得结论:一个指针从起始点出发,一个指针从相遇点出发,两个指针必在入环点相遇。

方法一:

       定义两个指针,一个从起始点出发,一个从相遇点出发。逐步移动,最终相遇时即为入环点。

方法二:

       当作相交链表处理。将环在相遇点与相遇点的下一个节点断开,定义一个指针为起始点,定义另一个指针为相遇点的下一个,将寻找入环点转换为寻找链表的相交点。

        以下为找寻相交点的代码:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值