題目描述:
給定乙個鍊錶,返回鍊錶開始入環的第乙個節點(即環的入口)。如果鍊錶無環,返回 null。
解題思路:
每經過乙個節點,都判斷之前是否經過這個節點。如果沒有經過,將這個節點新增到雜湊表中;如果經過這個節點,該節點就是環的入口,直接返回這個節點。
解題思路:
在解決這道題目時,第一步就是使用雙指標判斷是否有環,這個過程和之前的 141. 環形鍊錶i: 判斷鍊錶是否有環 沒有什麼差別,重點是第二步,如果有環如何找到入環口?
如下圖所示,快慢指標從起點 a 開始,走過 a 個指標到達入環口 b 點,慢指標又走過 b 個指標,在 c 點被快指標追上。
這個過程中,因為快指標先入環,所以在慢指標進入環之前,快指標可能就已經繞著環走了很多圈了,所以快指標走過的路程(節點數) s = a+(b+c)*n+b,其中 n 為 快指標在環中走過的圈數,慢指標走過的路程(節點數) s = a + b,而我們設定的快慢指標,快指標的速度是慢指標的 2 倍,因此快指標走過的路程也是慢指標的2倍,於是有了下面的推導
2 ∗s
慢=s快
2∗(a
+b)=
a+n∗
(b+c
)+ba
=(n−
1)∗(
b+c)
+c2*s_慢 = s_快\\ \begin 2*(a+b)=a+n*(b+c)+b\\ a=(n-1)*(b+c)+c \end
2∗s慢=
s快2
∗(a+
b)=a
+n∗(
b+c)
+ba=
(n−1
)∗(b
+c)+
c根據 a=(n-1)*(b+c)+c 得到了乙個結論:
s ab
=scb
+k∗s
環長s_ = s_ + k*s_\\
sab=s
cb+
k∗s環
長這樣我們就得到了找到入環口的點 b 位置的方案了,讓乙個節點 m 從起點 a 出發,每次走一步,同時讓乙個節點 n 從快慢指標相遇點 c 出發,每次走一步,那麼當 m 到達 入環口 b 的時候,n 正好在環內走了 k 圈之後到達 b 點,所以 m,n 的相遇點就是環的入口點。
/**
* definition for singly-linked list.
* class listnode
* }*/public
class
solution
// 如果有環,找到入環口位置
注意:如果是使用之前在 leetcode 141 中的方法,slow 指標初始值是 head,而 fast 指標的初始值是 head.next 的話,推導公式不同,因為我們先讓快指標走了一步,所以應該是
2 ∗s
慢+1=
s快2∗
(a+b
)+1=
a+n∗
(b+c
)+ba
+1=(
n−1)
∗(b+
c)+c
2*s_慢 + 1= s_快\\ \begin 2*(a+b) + 1=a+n*(b+c)+b\\ a+1=(n-1)*(b+c)+c \end
2∗s慢+
1=s快
2∗(
a+b)
+1=a
+n∗(
b+c)
+ba+
1=(n
−1)∗
(b+c
)+c
public listnode detectcycle
(listnode head)
fast = head;
slow = slow.next;
// 這步是關鍵,不然兩個指標總是差一步,死迴圈。
while
(fast != slow)
return fast;
}
142 環形鍊錶 II
還是快慢指標的問題,當發現有環時,將fast指向head,fast一次向前移動乙個節點,則fast和slow一定會在環的入口相遇.證明 設s為slow指標走的節點個數,m為環的入口距head的位置 則第一次相遇時,fast和head相對於環入口的位置相同,fast在環中的相對於環入口的位置在 2s ...
142 環形鍊錶 II
給定乙個鍊錶,返回鍊錶開始入環的第乙個節點。如果鍊錶無環,則返回null。說明 不允許修改給定的鍊錶。高階 你是否可以不用額外空間解決此題?definition for singly linked list.struct listnode class solution node set.insert...
142 環形鍊錶 II
給定乙個鍊錶,返回鍊錶開始入環的第乙個節點。如果鍊錶無環,則返回 null。為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置 索引從 0 開始 如果 pos 是 1,則在該鍊錶中沒有環。說明 不允許修改給定的鍊錶。示例 1 輸入 head 3,2,0,4 pos 1 輸出...