環形鏈表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 的進階版,一樣須要用到快慢指針,但要更復雜些。spa
如圖,假設起點到入環點的距離爲 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; } }