142. 环形链表 II

142. 环形链表 II - 力扣(LeetCode)

思路:

与题目141. 环形链表-CSDN博客相似。

先找到快慢指针相遇的位置。

假设从head到环的入口总共有a步,环有b步。

快指针走了 f 步, 慢指针走了 s 步。慢指针走1步,快指针走2步,所以快指针走的步数一定是慢指针的2倍,即 f = 2s。

相遇后,快指针一定比慢指针多走 b 的整数倍步,f = s + nb。

两个式子相减得到 s = nb

从head走到环入口有 a 步,在走环的整数倍,还能再次到达入口,即 a + nb 也是入口。

因为此时 s 已经是 b 的整数倍了,所以距离入口位置有 a 步。

所以如果从head 和 s 同时开始走,相遇时二者都走了 a 步,相遇的位置就是入口。

总结:

  1. 走a+nb步一定是在环入口
  2. 第一次相遇时慢指针已经走了nb步

代码:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode p1 = dummy, p2 = dummy;
        while(p1 != null && p1.next != null) {
            p1 = p1.next.next;
            p2 = p2.next;
            // 相遇了,慢指针p2走了 nb 步
            if(p1 == p2) {
                ListNode t = dummy;
                // t 和 s 同时开始走 相遇时都走了 a 步
                while(t != p2) {
                    t = t.next;
                    p2 = p2.next;
                }
                // 相遇的位置就是入口
                return t;
            }
        }
        // 快慢指针没有相遇,不存在环
        return null;
    }
}

参考:

142. 环形链表 II - 力扣(LeetCode)题解

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值