力扣142题 环形链表

题目解析

找到环的入口

定义快慢指针,f 每次走两步,l 每次走一步,所以 f 走过的节点数是 l 的两倍 f = 2l,如果存在环,那么走的快的 f 和走到慢的 l 会在环上的一点相遇。

设走到环的入口前有a个节点,f 和 l 相遇在环上的第 k 个节点。
当 f 和 l 相遇时:
式1:f 走过的节点数 f = a + n圈 + k
式2:f 走过的节点数 f = a + n1圈 + k ( n1 < n )
又因为 f =2l ,所以根据数学关系 f - l = 2l - l = l = 式1 = 式2 = (n - n1)圈

环的入口在哪里?

真好走 a+整数个环
第一次相遇 f 和 l 都正好走了整数个环,所以再走 a 步,到环的入口

怎么正好走 a 步

让 l 回到起点,l 和 f 都一次一步走,相遇时正好在环口,走了 a 步。
( l 从1 走到4,f 从5走到4)

代码实现

public ListNode detectCycle(ListNode head) {
        //找到环的入口 正好走 a + x圈
        ListNode f = head;
        ListNode l = head;
        //f 一次走两步 l 一次走1步,当第一次相遇
        // f = a + n圈 + k步 = 2l  l = a + n1圈 + k步
        //f-l=2l-l=l = (n -n1)圈
        //找到第一次相遇
        while (f != null && f.next != null) {
            f = f.next.next;
            l = l.next;
            if(l == f){
                //相遇的f l 在同一个节点
                //找到环的入口:此时 l = (n -n1)圈,再走 a 步,正好走到入口
                //怎么确定 a? 此时 f=l ,l回到起点,一次都走一步,正好走a步在环口相遇
                l = head;
                while (l != f){
                    f = f.next;
                    l = l.next;
                }
                return l;
            }
        }
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值