有環(huán)鏈表的判斷以及入口點(diǎn)計(jì)算

題意:給定一個(gè)單向鏈表,求判斷該鏈表是否為帶環(huán)鏈表并求出該環(huán)的入口點(diǎn)

來(lái)源地址:Chasiny

例如下圖凡简,一個(gè)帶環(huán)的單向鏈表


algorithm01.png

方法一:使用輔助結(jié)構(gòu)Map實(shí)現(xiàn)

  • 思想:用一個(gè)map存儲(chǔ)所有鏈表節(jié)點(diǎn)的地址,每次存前判斷該節(jié)點(diǎn)是否在map中精肃,如果存在,則該鏈表為帶環(huán)鏈表并且該節(jié)點(diǎn)為環(huán)的入口帜乞。
  • 優(yōu)點(diǎn):簡(jiǎn)單
  • 缺點(diǎn):需要較大的輔助空間
#include <iostream>
#include <map>
using namespace std;

struct Node{
        int Val;
        Node* next;
};

Node* Init(){
        int nodeData[]={1,2,3,4,5,6,7,8,9,10,11,12};
        Node* node[12];

        for(int i=0;i<sizeof(node)/sizeof(Node*);i++){
                node[i]=new Node;
                node[i]->Val=nodeData[i];
                cout<<"create node "<<node[i]->Val<<endl;
        }

        for(int i=0;i<sizeof(node)/sizeof(Node*)-1;i++){
                node[i]->next=node[i+1];
        }

        node[sizeof(node)/sizeof(Node*)-1]->next=node[7];

        return node[0];
}

int main(){

        Node* head=Init();
        map<Node*,int> nodeMap;
        while(head){
                if(nodeMap[head]==0){
                        nodeMap[head]=1;
                }else{
                        cout<<"this is a ring list, entrance is: "<<head->Val<<endl;
                        break;
                }
                head=head->next;
        }

        return 0;
}

輸出結(jié)果如下

create node 1
create node 2
create node 3
create node 4
create node 5
create node 6
create node 7
create node 8
create node 9
create node 10
create node 11
create node 12
this is a ring list, entrance is: 8

方法二:使用快慢指針

判斷是否帶環(huán)

  • 思想:分別用一個(gè)快指針跟一個(gè)慢指針同時(shí)從鏈表頭開(kāi)始移動(dòng)司抱,快指針的速度是慢指針的兩倍,當(dāng)快慢指針相遇黎烈,則該鏈表為帶環(huán)鏈表习柠。
  • 優(yōu)點(diǎn):不需要大的輔助空間
  • 缺點(diǎn):比較復(fù)雜

判斷帶環(huán)的步驟


algorithm03.png

algorithm04.png

algorithm05.png

algorithm06.png

algorithm07.png

algorithm08.png

algorithm09.png

algorithm10.png

algorithm11.png

algorithm12.png

algorithm13.png

源碼實(shí)現(xiàn)

判斷環(huán)的入口:分別用兩個(gè)指針匀谣,一個(gè)在快慢指針相遇的地方開(kāi)始移動(dòng),一個(gè)從鏈表的頭節(jié)點(diǎn)開(kāi)始移動(dòng)资溃,當(dāng)這兩個(gè)指針相遇時(shí)武翎,改節(jié)點(diǎn)就是環(huán)的入口點(diǎn)

證明:

  • 設(shè)從頭節(jié)點(diǎn)到環(huán)入口的距離為L(zhǎng),環(huán)的入口按鏈表順序到快慢指針相遇的節(jié)點(diǎn)的距離為M溶锭,快慢指針相遇的節(jié)點(diǎn)按鏈表順序到環(huán)的入口的距離為K宝恶,環(huán)的周長(zhǎng)為P,即P - M = L趴捅,如下圖所示


    algorithm02.png

快指針的速度為慢指針的兩倍垫毙,即

  • S(快)=S(慢)*2

由于到兩個(gè)指針相遇的地點(diǎn)時(shí),快指針比慢指針多走的路程是環(huán)的周長(zhǎng)的整數(shù)倍(快指針追趕慢指針拱绑,所以快指針至少比慢指針多走一環(huán)的距離)综芥,即

  • S(快) - S(慢) = n1 * P (n1 >= 1)
  • 得 S(慢) = n1 * P (n1 >= 1)
  • 又有S(慢) = L + M + n2 * P (n2 >= 0)
  • 得 n1 * P = L + M + n2 * P (n1 >= 1 , n2 >= 0)
  • 得 (n1 - n2) * P = L + M
  • (n1 - n2) * P = L + (P - K)
  • (n1 - n2 -1) * P + K = L

因此從相遇節(jié)點(diǎn)按照鏈表順序移動(dòng)L,停下來(lái)的位置就是環(huán)的入口點(diǎn)

求環(huán)的入口的步驟


algorithm14.png

algorithm15.png

algorithm16.png

algorithm17.png

algorithm18.png

algorithm19.png

algorithm20.png

algorithm21.png

快慢指針代碼樣例

#include <iostream>
#include <map>
using namespace std;

struct Node{
        int Val;
        Node* next;
};

Node* Init(){
        int nodeData[]={1,2,3,4,5,6,7,8,9,10,11,12};
        Node* node[12];

        for(int i=0;i<sizeof(node)/sizeof(Node*);i++){
                node[i]=new Node;
                node[i]->Val=nodeData[i];
                cout<<"create node "<<node[i]->Val<<endl;
        }

        for(int i=0;i<sizeof(node)/sizeof(Node*)-1;i++){
                node[i]->next=node[i+1];
        }

        node[sizeof(node)/sizeof(Node*)-1]->next=node[7];

        return node[0];
}

int main(){

        Node* head=Init();
        Node* qPos=head;
        Node* sPos=head;
        while(qPos){
                sPos=sPos->next;
                if(!qPos->next){
                        cout<<"this is not a ring list\n";
                        break;
                }
                qPos=qPos->next->next;

                if(sPos==qPos){
                        cout<<"this is a ring list\n";
                        break;
                }
        }

        Node* tPos=head;
        while(true){
                tPos=tPos->next;
                sPos=sPos->next;
                if(tPos==sPos){
                        cout<<"entrance is: "<<sPos->Val<<endl;
                        break;
                }
        }

        return 0;
}

結(jié)果是

create node 1
create node 2
create node 3
create node 4
create node 5
create node 6
create node 7
create node 8
create node 9
create node 10
create node 11
create node 12
this is a ring list
entrance is: 8
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末猎拨,一起剝皮案震驚了整個(gè)濱河市膀藐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌红省,老刑警劉巖消请,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異类腮,居然都是意外死亡臊泰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)蚜枢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缸逃,“玉大人,你說(shuō)我怎么就攤上這事厂抽⌒杵担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵筷凤,是天一觀的道長(zhǎng)昭殉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)藐守,這世上最難降的妖魔是什么挪丢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮卢厂,結(jié)果婚禮上乾蓬,老公的妹妹穿的比我還像新娘。我一直安慰自己慎恒,他們只是感情好任内,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布撵渡。 她就那樣靜靜地躺著,像睡著了一般死嗦。 火紅的嫁衣襯著肌膚如雪趋距。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天越除,我揣著相機(jī)與錄音节腐,去河邊找鬼。 笑死廊敌,一個(gè)胖子當(dāng)著我的面吹牛铜跑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骡澈,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锅纺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了肋殴?” 一聲冷哼從身側(cè)響起囤锉,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎护锤,沒(méi)想到半個(gè)月后官地,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烙懦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年驱入,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氯析。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亏较,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掩缓,到底是詐尸還是另有隱情雪情,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布你辣,位于F島的核電站巡通,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏舍哄。R本人自食惡果不足惜宴凉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蠢熄。 院中可真熱鬧跪解,春花似錦、人聲如沸签孔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)饥追。三九已至图仓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間但绕,已是汗流浹背救崔。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捏顺,地道東北人六孵。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像幅骄,于是被迫代替她去往敵國(guó)和親劫窒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容