142. 环形链表 II

257 阅读1分钟

题目描述

image.png

方法一;快慢指针

  • 快慢指针一定在环内相遇,
    • 原因:快指针会在圈内一直绕,当慢指针进入圈后,快指针会追赶慢指针,直到套圈。并且慢指针最多走完一个圈的距离
  • 慢指针肯定不会走多圈,会在一圈之内被追上。
    • 假设fast在slow前x个单位,假设环长度为L, fast需要追赶L-x长度,追赶的速度为2-1=1,追赶上所花费的时间为L-x/1 = L-x。在这段时间内,slow走的距离为 1 * (L-x) = L - x, 永远小于L,因此slow不可能走完一整个环。

CFBC8DDEB66CE8C3A1BE2FA030ADB198.png

  • 所以,再用两个指针,一个从头节点开始走,另一个从相遇点开始走,两者相遇处即为入环处。
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head, slow = head;
        while (fast != null && fast.next != null && slow != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) { //环中相遇
                while (fast != head) {
                    fast = fast.next;
                    head = head.next;
                }
                return head;
            }
        }
        return null;
    }
}

方法二:用set记录访问过的节点

public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        ListNode cur = head;
        while (cur != null){
            if (set.contains(cur)) {
                return cur;
            } else {
                set.add(cur);
                cur = cur.next;
            }
        }
        return null;

    }
}