單鏈表有環的情景如下,爲了方便起見,假定入口之前的鏈表長度爲L,循環長度爲K
循環鏈表示意圖
我們可以用兩個指針,p1每次移動一格,p2每次移動兩格,初始化都爲頭結點HEAD
隨着指針慢慢推進,一定會出現以下的情況
某一時刻兩指針的情況
第一步
現在,我們可以假定再經過t次移動之後,兩者會在某一處相遇,對照上圖
對於P1,t次移動後的位置爲t % K
對於P2, t次移動後的位置爲(x + 2 * t) % K
P1和P2相遇的充要條件爲 t % K = (x + 2 * t) % K
顯然,t = K - x就可以滿足條件,至此,P1總共遍歷了 L + K - x 個結點,也就是說P1不需要遍歷所有的結點便可以和P2相遇,即有循環
當然,如果在遍歷過程中只要P2或者P2->next爲NULL,就break,說明此鏈表沒有環
第二步
現在要求循環的起始點,顯然上圖中是陰影部分的0處,
由上面一步可知,當P1移動到所示位置時用了L次,P2移動的格數爲 2*L ,並且滿足
2*L = L + x + r * K 即 L = x + r *k (r>=0爲P2在循環裏面轉的圈數) #1
在上一步中,最後P2的位置爲 K - x, 要讓P2移動到陰影部分0的位置,只需要P2再移動L格,
因爲根據上面的等式#1 , P2移動L 格之後的位置爲
(K - x + L) % K = (K - x + x + r * K )= ((r + 1) * K) % K = 0
剛好在交匯處
那麼,怎麼才能讓P2移動L次呢,顯然,如果我們將P1再次指向HEAD,每次移動一格,並且此時P2每次也移動一格
移動L次之後,p1也在0處,兩者便相遇了,相遇的地方就是所求的交匯處,那麼我們要做的就是
不斷地移動P1和P2直到兩者相遇,相遇的結點便就是所求結點
代碼明天奉上,晚安