142 環形鍊錶 II

2021-10-22 18:53:37 字數 2481 閱讀 8723

題目描述:

給定乙個鍊錶,返回鍊錶開始入環的第乙個節點(即環的入口)。如果鍊錶無環,返回 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 輸出...