leetcode 142. 環形鏈表 II golang實現

描述
給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。
思路

原作者地址

當fast == slow時, 兩指針在環中 第一次相遇 。下面分析此時fast 與 slow走過的 步數關係 :

設鏈表共有 a+ba+b 個節點,其中 鏈表頭部到鏈表入口 有 aa 個節點(不計鏈表入口節點), 鏈表環 有 bb 個節點(這裏需要注意,aa 和 bb 是未知數,例如圖解上鍊表 a=4a=4 , b=5b=5);設兩指針分別走了 ff,ss 步,則有:
fast 走的步數是slow步數的 22 倍,即 f = 2sf=2s;(解析: fast 每輪走 22 步)
fast 比 slow多走了 nn 個環的長度,即 f = s + nbf=s+nb;( 解析: 雙指針都走過 aa 步,然後在環內繞圈直到重合,重合時 fast 比 slow 多走 環的長度整數倍 );
以上兩式相減得:f = 2nbf=2nb,s = nbs=nb,即fast和slow 指針分別走了 2n2n,nn 個 環的周長 (注意: nn 是未知數,不同鏈表的情況不同)。


如果讓指針從鏈表頭部一直向前走並統計步數k,那麼所有 走到鏈表入口節點時的步數 是:k=a+nb(先走 aa 步到入口節點,之後每繞 11 圈環( bb 步)都會再次到入口節點)。
而目前,slow 指針走過的步數爲 nbnb 步。因此,我們只要想辦法讓 slow 再走 aa 步停下來,就可以到環的入口。
但是我們不知道 aa 的值,該怎麼辦?依然是使用雙指針法。我們構建一個指針,此指針需要有以下性質:此指針和slow 一起向前走 a 步後,兩者在入口節點重合。那麼從哪裏走到入口節點需要 aa 步?答案是鏈表頭部head。

如果讓指針從鏈表頭部一直向前走並統計步數k,那麼所有 走到鏈表入口節點時的步數 是:k=a+nb(先走 aa 步到入口節點,之後每繞 11 圈環( bb 步)都會再次到入口節點)。
而目前,slow 指針走過的步數爲 nbnb 步。因此,我們只要想辦法讓 slow 再走 aa 步停下來,就可以到環的入口。
但是我們不知道 aa 的值,該怎麼辦?依然是使用雙指針法。我們構建一個指針,此指針需要有以下性質:此指針和slow 一起向前走 a 步後,兩者在入口節點重合。那麼從哪裏走到入口節點需要 aa 步?答案是鏈表頭部head。
實現
func DetectCycle(head *ListNode) *ListNode {
	slow := head
	fast := head

	for {
		if fast == nil || fast.Next == nil{
			return nil
		}
		slow = slow.Next
		fast = fast.Next.Next
		if fast == slow{
			break
		}
	}
	cur := head
	for cur != slow{
		cur = cur.Next
		slow = slow.Next
	}

	return cur
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章