环形链表入口点证明[leetcode142]

首先需要使用Floyd 判圈算法(又称龟兔赛跑算法)的快慢指针思想找到环内快慢指针相遇点c。
如图所示:
环形链表入口点证明[leetcode142]_第1张图片
假设起点为a,环的入口点为b。起点a到环入口点的距离为x,环的入口点到快慢指针相遇点距离为y。

从快慢指针相遇点将慢指针往回倒退y步到达点b,由于快指针速度是慢指针的两倍,故快指针会倒退到c'点,其中b到c'的距离也为y。即当慢指针走到b点时,快指针的位置在c'。由于慢指针此时走了x步,故快指针从a走2x步到达了c'点。进而等价于快指针从b点走x距离会走到c'点

由于bc = bc',故从c点走x距离会走到b点。a->b == c->b[当然c到b可能走了不止一圈]。

综上,当快慢指针相遇后,设置两指针p1、p2,p1起点为a,p2起点为c,同时一走一步,当p1和p2相遇,即为环的入口点。p1、p2可重用快慢指针。

public ListNode detectCycle(ListNode head) {
    ListNode slow = head, fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
        if (slow == fast) break;
    } 
    if (fast == null || fast.next == null) return null;

    slow = head;
    while (slow != fast) {
        slow = slow.next;
        fast = fast.next;
    }
    return slow;
}

你可能感兴趣的:(leetcode算法)