環形鏈表 II 轉載 https://blog.csdn.net/forever______/article/details/85103234#_1

給定一個鏈表,返回鏈表開始入環的第一個節點。 若是鏈表無環,則返回 null。node

爲了表示給定鏈表中的環,咱們使用整數 pos 來表示鏈表尾鏈接到鏈表中的位置(索引從 0 開始)。 若是 pos 是 -1,則在該鏈表中沒有環。bash

說明:不容許修改給定的鏈表。ui

img

示例 1:spa

輸入:head = [3,2,0,-4], pos = 1
輸出:tail connects to node index 1
解釋:鏈表中有一個環,其尾部鏈接到第二個節點。
複製代碼

img

示例 2:3d

輸入:head = [1,2], pos = 0
輸出:tail connects to node index 0
解釋:鏈表中有一個環,其尾部鏈接到第一個節點。
複製代碼

img

示例 3:指針

輸入:head = [1], pos = -1
輸出:no cycle
解釋:鏈表中沒有環。
複製代碼

用兩個指針同時遍歷鏈表,快指針每次走兩步,慢指針每次走一步。若是鏈表中有環,那麼他們終將相遇。可證:自他們相遇後,指針1從起點每次走一步,指針2從相遇點每次走一步,指針1和指針2相遇處就是環的起點。證實以下:code

以下圖,設Y點爲環起點,Z點爲快慢指針相遇點,abc爲這幾個關鍵節點間的路程(可能包括不少節點)。cdn

由於,相遇時快指針走過的路程確定爲慢指針走過的路程的2倍。得:blog

(a+b)2 = a+b+(b+c)n //n>=1,n爲快指針在相遇前繞環的圈數索引

解方程得 a = (b+c)(n-1)+c

因此:

當n=1時,a=c

當n>1時,a=c+n圈

得證。

img

時間複雜度O(n)

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode 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;
        }
        while( head != slow ){
            head = head.next;
            slow = slow.next;
        }
        return head;
    }
}
複製代碼
相關文章
相關標籤/搜索