Flodyne judgment circle method to solve the problem of linked list Cycle

本文详细介绍了如何使用快慢指针检测链表中的环,并找到环的起始结点。通过设定快慢指针的速度差,当两者相遇时可以确定环的存在。接着分析了相遇点与环起始结点的关系,最后给出了AC代码实现。这种方法在数据结构和算法中具有重要的应用价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
在这里插入图片描述

  • 设置快慢指针,寻找数量关系。快指针为fast,慢指针为slow。快指针一次走2步,满指针一次走一步。
  • 则如果链表中有环,快慢指针最终一定会在环上相遇。
    • 相遇时,快指针比满指针多走整数圈。

设相遇时,快指针走的步数为fast.lengthfast.lengthfast.length,满指针走的步数为slow.lengthslow.lengthslow.length,图中链表圈的长度为cycle.lengthcycle.lengthcycle.length。有fast.length=2∗slow.lengthfast.length = 2 * slow.lengthfast.length=2slow.length

  • 第一次相遇时具有数量关系。
    fast.length−slow.length=n⋅cycle.lengthfast.length - slow.length = n\cdot cycle.lengthfast.lengthslow.length=ncycle.length
  • 慢指针第一次与快指针相遇时,慢指针至多走完一圈;
    • 考虑当慢指针刚进入链表的时刻,快指针就在慢指针之前 +1的距离的情形。这时快指针要追上慢指针需要的时刻最长。
    • 慢指针走完一圈时,快指针已经走完两圈。所以慢指针在走完一圈中一定存在某一位置与快指针相遇。
    • 于是slow.length=n⋅cycle.lengthslow.length = n\cdot cycle.lengthslow.length=ncycle.length

设慢指针进入圈之前走过的步数为xxx,进入圈之后走过的步数为yyy。则slow.length=x+y=n⋅cycle.lengthslow.length = x + y = n \cdot cycle.lengthslow.length=x+y=ncycle.length
- 所以从链表头到环起始结点的步数x=n⋅cycle.length−y(a)x = n \cdot cycle.length - y(a)x=ncycle.lengthya

考虑快慢指针相遇的位置,距离链表环起始结点的步数为cycle.length−y(b)cycle.length - y\quad(b)cycle.lengthy(b)
由式a和式b的数量关系可知,可以从链表头结点和相遇结点,分别设置每次都走一步的指针(设为指针AAABBB)。

  • 当两个指针第一次相遇时,相遇结点一定存在于环上。
  • 且相遇结点一定是环起始结点,这是因为:
    • 首先相遇时两个指针走的步数相同。
    • 当指针AAA第一次进入环中第一个结点,需要走的步数为n⋅cycle.length−yn \cdot cycle.length - yncycle.lengthy,而此时指针BBB走过的距离也为这个值。当B走过这个值时,由式B可知B恰好处于进入环的首个结点。因此这个进入环的首个结点即目标结点恰好是他们俩第一次相遇的位置

AC代码如下

public ListNode detectCycle(ListNode head) {
        if(head == null)
            return null;
        ListNode slow = head;
        ListNode fast = head;
        while(slow!=null && fast!=null)
        {
            slow = slow.next;
            fast = fast.next;
            if(fast == null)
                break;
            fast = fast.next;
            if(slow!= null && slow == fast)   //相遇代表找到了图中的圈
            {
                fast = head;
                while(slow!=fast)
                {
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow;
            }
        }
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值