【LeetCode】142-環形鏈表II(含推理過程)

環形鏈表IIjava

題目

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

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

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

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

示例 3:
輸入:head = [1], pos = -1
輸出:no cycle
解釋:鏈表中沒有環。

進階:
你是否能夠不用額外空間解決此題?

解題思路

這道題目是 141 的進階版,一樣須要用到快慢指針,但要更復雜些。

leetcode142.jpgspa

如圖,假設起點到入環點的距離爲 a,順時針方向入環點到相遇點的距離爲 b,相遇點到入環點的距離爲 c。則有:指針

慢指針走過的路程:a + b
快指針走過的路程:a + b + n(b + c)(n 爲圈數)

因爲快指針速度是慢指針的 2 倍,故有:code

2(a + b) = a + b + n(b + c)

公式可轉化爲:blog

a + b = n(b + c)

進一步可轉化爲:索引

a = n(b + c) - b
a = n(b + c) - b - c + c
a = (n - 1)(b + c) + c

即 a 的距離等於相遇點到入環點的距離 + n 圈的距離。 leetcode

由此,咱們能夠在快慢指針相遇後,將快指針移動到頭節點,慢指針在相遇點。快慢指針同時前進(每次前進 1 步),當快指針走完 a 距離時,慢指針恰好走好 c 距離 + n 圈的距離,它們相遇的地方就是入環點。rem

代碼

class Solution { 
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
                return null;
        }
    
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            // 先找到相遇點
            if (fast == slow) {
                fast = head;
                // 再找到入環點
                while (fast != slow) {
                    fast = fast.next;
                    slow = slow.next;
                }
                return slow;
            }
        }
        
        return null;
    }
}
相關文章
相關標籤/搜索