單向鏈表環問題的全面解析(判斷環,環的長度,環的入口)

最近複習面試,遇到鏈表內的環問題,研究了一下,如今記錄一下。廢話很少說,先上圖。面試

如上圖,一個單向鏈表中若是有環,則其形狀相似於「6」,有一個環的的入口,就是上圖的紫色點。spa

下面說一下常見的問題的解決辦法及其原理。指針

一.判斷單鏈表是否有環數學

使用兩個slow, fast指針從頭開始掃描鏈表。指針slow 每次走1步,指針fast每次走2步。若是存在環,則指針slow、fast會相遇,例如上圖的綠點就是相遇點——鏈表中的第6個點;若是不存在環,指針fast遇到NULL退出。ast

這裏有個定律:fast和slow必定會環內相遇(1),並且是在slow走完環的第一圈以前相遇(2)。爲何呢?原理

首先,fast和slow必定會在環內相遇這是顯然的,由於只有在環內,fast纔有可能經過比slow多走一圈而後從後面追上來。那麼爲何會在slow走第一圈時相遇呢?有個直觀解釋。設鏈表中環外的長度是a(上圖中a=2),環內長度是b(上圖b=5),那麼當a=0時,整一個鏈表就是一個大環,fast和slow就會在頭結點、也便是環的終點相遇!由於這時候fast恰好走了兩圈而slow走了一圈。這是極端的狀況,當環的長度變小時,即a!=0時,slow就會在還沒走完一圈的時候被fast追上。這是直觀的解釋,下面能夠用數學嚴謹證實。im

設相遇的時候,fast和slow分別走了2l步和l步,由(1)能夠知道,l>a,兩者相遇時有:鏈表

                        (l-a) mod b = (2l-a) mod b    (3)img

mod是取餘的意思,設(3)同餘c,這時候slow和fast在環上分別走了k1圈和k2圈,這時候有:移動

                           l - a + c = bk1             (4)

                           2l - a + c= bk2             (5)

首先證實一下slow和fast爲何必定會相遇的問題。(5)式減(4)式有:

                        l = (k2-k1)b                (6)

那麼fast和slow能不能相遇取決於(6)式能不能被知足,顯然這是能夠的,並且有無窮個解。並且第一個解就是k2-k1=1,l=b的時候(7),也就是fast和slow第一次相遇的時候!因爲k1,k2的取值範圍是正整數,因此最小的取值,也就是第一次相遇時的取值一定是k2=2 ,k=1!那麼基本上全部問題迎刃而解。k2=2 ,k=1意味着,fast和slow確定是在fast在走環的第2圈、slow在走環的第1圈的時候第一次相遇!這就解釋了問題(2)。

二.求有環單鏈表的環長

求環長即求b,由(7)知道,b=l,即環長等於slow指針走過的長度

三.求有環單鏈表的環鏈接點位置

因爲k1 = 1 ,l = b,因此(4)式能夠化簡爲 a = c,c表示的意義是什麼?c表示slow指針還差c步就能夠走完第一圈,即走到環的入口處,a = c 意味着slow指針和頭指針到環入口的距離是同樣的!因此只須要將頭指針和slow指針同時向前移動,相遇點即爲環的入口。

四.求有環單鏈表的鏈表長

即求 a + b = a + l,a和l都可以在上述步驟中求得。

完。

相關文章
相關標籤/搜索