leetcode 142

61 阅读2分钟

1. 题目

leetcode.cn/problems/li…

2. 题目分析

该题主要是做两件事:

  1. 分析是否有环
  2. 找到环的入口

2.1 分析是否有环

当我们需要分析是否有环的时候,可以使用两个快慢指针来进行处理,一个指针走两步,一个指针走一步,如果是有环的,那么这两个指针最终会相遇。如果出现快指针的next 或者 next.next为null,那么说明没有环。

2.2 怎么找到环的入口呢?

我们假设指针a走了x步,则指针b走了2x步; 我们称指针a指针b相遇的点为交点。假设环的入口到交点的距离为t,从交点需要再走x步才能到达交点,这时候我们可以发现从入口到交点的和从交点到交点有重合的一段距离,即从环的入口到交点的距离为t,这段距离是重合的。此时当我们将指针b重新指向入口按1的步长走,将指针a按1的步长走,当他们相遇的时候就是环的入口。

3. 代码实现

public ListNode detectCycle(ListNode head) {
    //case有为空的情况
    if (null == head) {
        return head;
    }
    //我想从ab两个指针都从头开始但是这样子的话我while就永远是false了,所以加了一下c标识第一次还是不是第一次
    int c = 0;
    ListNode a = head, b = head;
    //a每次进一位,b每次进两位
    //当a b 相遇的时候就说明有环了,c == 0 说明是第一次
    while (c == 0 || a != b) {
        //遇到为空的,说明不是环,直接退出
        if (b.next == null || b.next.next == null) {
            return null;
        }
        a = a.next;
        b = b.next.next;
        //标识
        c++;
    }

    //把b指向头节点
    b = head;
    //一个从头,一个从交点出发,相遇的地方就是入口了
    while (a != b) {
        a = a.next;
        b = b.next;
    }
    return a;
}