給定乙個鍊錶,返回鍊錶開始入環的第乙個節點。 如果鍊錶無環,則返回 null。為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鍊錶中沒有環。說明:不允許修改給定的鍊錶。
示例 1:
示例 2:
示例 3:
這類鍊錶題目一般都是使用雙指標法解決的,例如尋找距離尾部第k個節點、尋找環入口、尋找公共尾部入口等。
演算法流程:
1.雙指標第一次相遇: 設兩指標 fast,slow 指向鍊錶頭部 head,fast 每輪走 2 步,slow 每輪走 1 步;
(1)第一種結果: fast 指標走過鍊錶末端,說明鍊錶無環,直接返回 null;若有環,兩指標一定會相遇。因為每走 1 輪,fast 與 slow 的間距 +1,fast 終會追上 slow;
(2)第二種結果: 當fast == slow時, 兩指標在環中第一次相遇 。下面分析此時fast 與 slow走過的步數關係 :
設煉表共有 a+b個節點,其中 鍊錶頭部到鍊錶入口 有 a 個節點(不計鍊錶入口節點), 鍊錶環有 b 個節點(這裡需要注意,a 和 b是未知數,例如**上鍊表 a=4 , b=5);設兩指標分別走了 f,s 步,則有:
1)fast 走的步數是slow步數的 2 倍,即 f = 2s;(解析: fast 每輪走 2 步)
2)fast 比 slow多走了 n 個環的長度,即 f = s + nb;( 解析: 雙指標都走過a 步,然後在環內繞圈直到重合,重合時 fast 比 slow 多走 環的長度整數倍 );
3)以上兩式相減得:f = 2nb,s = nb,即fast和slow 指標分別走了 2n,n 個環的周長 (注意: n 是未知數,不同鍊錶的情況不同)。
2.目前情況分析:
(1)如果讓指標從鍊錶頭部一直向前走並統計步數k,那麼所有走到鍊錶入口節點時的步數是:k=a+nb(先走a步到入口節點,之後每繞 1 圈環(b 步)都會再次到入口節點)。
(2)而目前,slow 指標走過的步數為nb步。因此,我們只要想辦法讓slow再走a 步停下來,就可以到環的入口。
(3)但是我們不知道 a 的值,該怎麼辦?依然是使用雙指標法。我們構建乙個指標,此指標需要有以下性質:此指標和slow 一起向前走 a 步後,兩者在入口節點重合。那麼從**走到入口節點需要 a 步?答案是鍊錶頭部head。
3.雙指標第二次相遇:
(1)fast指標位置不變 ,將slow指標重新指向鍊錶頭部節點 ;slow和fast同時每輪向前走1步;此時 f = 2nb,s = 0;
(2)當 slow指標走到s = a步時,fast指標走到步f = 2nb+a,此時兩指標重合,並同時指向鍊錶環入口 。
4.返回fast指標的節點。
/**
* definition for singly-linked list.
* struct listnode
* };
*/class
solution
fast = fast-
>next-
>next;
slow = slow-
>next;
if(fast == slow)
} slow = head;
while
(fast != slow)
return fast;}}
;
時間複雜度 o(n):第二次相遇中,慢指標需走步數 a < a + b;第一次相遇中,慢指標須走步數 a + b - x < a + b,其中 x 為雙指標重合點與環入口距離;因此總體為線性複雜度;
空間複雜度 o(1):雙指標使用常數大小的額外空間。
判斷環形鍊錶
最開始想到的處理方式是整個陣列,把鍊錶元素乙個乙個放進去,直到有重複的,class solution def hascycle self,head listnode bool tgt while head head head.next if head and head.val in tgt retu...
環形鍊錶判斷
141 環形鍊錶 思路 將訪問過的放到乙個容器中,然後判斷當前訪問的節點是否已經存在容器內 141 1 放到容器中,判斷當前的節點是否在已訪問的容器內 bool hascycle listnode head return false 提交後 5 時間複雜度o n 空間複雜度o n 因為使用了額外的容...
環形鍊錶的判斷
給定乙個鍊錶,判斷鍊錶中是否有環。為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置 索引從 0 開始 如果 pos 是 1,則在該鍊錶中沒有環。示例 1 輸入 head 3,2,0,4 pos 1 輸出 true 解釋 鍊錶中有乙個環,其尾部連線到第二個節點。示例 2 輸...