給定一個鏈表,返回鏈表開始入環的第一個節點。 若是鏈表無環,則返回 null。 爲了表示給定鏈表中的環,咱們使用整數 pos 來表示鏈表尾鏈接到鏈表中的位置(索引從 0 開始)。 若是 pos 是 -1,則在該鏈表中沒有環。 說明:不容許修改給定的鏈表。node
示例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
解釋:鏈表中沒有環。
複製代碼
這道題思路其實很簡單,就是快指針每次前進兩格,慢指針前進一格,相遇以後將fast置爲頭結點和slow每次各自前進一格,再次相遇即爲環的起始位置。 OK,讓咱們嘗試來證實一下。 首先,咱們必須明確一點,若是鏈表有環,那麼快慢指針必定會相遇。來咱們看圖說話。
咱們設環外鏈表長度爲X(固然有可能爲0),從環的入口到相遇點的長度爲Y,環的周長爲C,那麼當即推: 快指針走過的長度爲 F = X + Y + n*C(n爲快指針超了慢指針n圈) 慢指針走過的長度爲 S = X + Y 由於: 1.快指針必定走的距離是慢指針的兩倍。 2.若是X=0,則快指針正好跑了兩圈,而慢指針跑了一圈,此時n=2但並不影響;若是X > 0,快指針總會在第二圈,即n = 1的時候追上慢指針,畢竟快指針先入環總歸是比快慢指針同時入環要早一些相遇。(原諒我,這個是我看出來的,可是確定是能夠證實的) 因此: 咱們看n=1的狀況 X + Y + C = 2 ( X + Y ) 即: X = C - Y 如今咱們能夠看出來,n=1這種狀況下,若是咱們有兩個指針,一個從頭結點開始,一個從快慢指針相遇點開始,同時一步一步地走,那麼新的相遇點就是環的入口啦。 特殊的狀況n=2時,其實咱們能夠看到快慢指針相遇點自己就是頭結點。那麼確定也是符合最上邊的結論的。 上碼吧老爺:
func detectCycle(head *ListNode) *ListNode {
slow,fast:=head,head
for{
//自始至終快慢未相遇,直接跳出就好
if fast==nil||fast.Next==nil {
break;
}
slow, fast = slow.Next,fast.Next.Next
//相遇了就像剛剛說的那樣咯
if slow==fast {
fast = head;
for{
if(slow==fast){
return slow
}
slow=slow.Next
fast=fast.Next
}
}
}
return nil
}
複製代碼
算法夢想家,來跟我一塊兒玩算法,玩音樂,聊聊文學創做,我們一塊兒天馬行空! spa