鏈表中環(huán)的入口節(jié)點

《劍指offer》面試題23:鏈表中環(huán)的入口節(jié)點

題目:給一個鏈表,若其中包含環(huán),請找出該鏈表的環(huán)的入口結點哮翘,否則,輸出null毛秘。

思路:
  原書中給出的思路:解決問題的第一步是如何確定一個鏈表有環(huán)饭寺。我們可以用兩個指針來解決這個問題。定義兩個指針叫挟,同時從鏈表的頭節(jié)點出發(fā)艰匙,一個指針一次走一步,另一個指針一次走兩步抹恳。如果走的快的指針追上了走得慢的指針员凝,那么鏈表就包含環(huán);如果走的快的指針走到了鏈表的末尾都沒有追上第一個指針奋献,那么鏈表就不包含環(huán)健霹。
  第二步是如何找到環(huán)的入口。我們還是用兩個指針來解決這個問題瓶蚂。先定義兩個指針p1和p2指向鏈表的頭節(jié)點骤公。如果鏈表的環(huán)中有n個節(jié)點,則指針p1先在鏈表上向前移動n步扬跋,然后兩個指針以相同的速度向前移動阶捆。當?shù)诙€指針指向環(huán)的入口節(jié)點時,第一個指針已經圍繞著環(huán)走了一圈钦听,又回到了入口節(jié)點洒试。
  剩下的問題是如何得到環(huán)中節(jié)點的數(shù)目。我們在前面提到判斷一個鏈表里是否有環(huán)時用到了一快一慢兩個指針朴上,如果兩個指針相遇垒棋,則表明鏈表中有環(huán)。兩個指針相遇的節(jié)點一定是在環(huán)中痪宰〉鸺埽可以從這個節(jié)點出發(fā),一邊繼續(xù)向前移動一邊計數(shù)衣撬,當再次回到這個節(jié)點時乖订,就可以得到環(huán)中節(jié)點數(shù)了。
  可以進行優(yōu)化的地方:如何得到環(huán)中節(jié)點的數(shù)目n具练?在判斷鏈表是否有環(huán)時用到了一快一慢兩個指針乍构,如果它們相遇,則表明鏈表中有環(huán)扛点。相遇時走的快的指針走的步數(shù)剛好比走的慢的指針走的步數(shù)多n步哥遮。這相當于運動學上的追擊問題岂丘,追上的條件是剛好多走“一圈”,在這里可以在兩個指針走的過程中對指針走的步數(shù)分別進行計數(shù)眠饮,當它們相遇時奥帘,計數(shù)之差就是環(huán)中節(jié)點的數(shù)目。對比書中給出的解法:不用在得到相遇節(jié)點之后再走n步得到n仪召。減少了常量級別的時間復雜度寨蹋。
  勘誤:之前認為在求環(huán)中節(jié)點數(shù)目n時可以利用運動學中的追擊問題的特性進行時間復雜度上的優(yōu)化,但在與同學的討論中發(fā)現(xiàn)之前的思路是錯誤的返咱,之前認為在判斷鏈表是否有環(huán)時用到的一快一慢兩個指針相遇的條件是快指針剛好多走"一圈"钥庇,但實際上是多走了n圈,之前在思考的過程中將兩個指針想象成兩個人在操場跑步進行追擊咖摹,人跑步的相遇條件確實是"一圈"评姨,但兩個指針一快一慢的"走","擦肩而過"并不叫相遇萤晴,只有當兩個指針指向同一節(jié)點時才是真的相遇吐句。

代碼如下:

public ListNode EntryNodeOfLoop(ListNode head) {
    // 得到相遇節(jié)點
    ListNode meetingNode = getMeetingNode(head);
    if (meetingNode == null) {
        return null;
    }
    // 計算環(huán)中節(jié)點總數(shù)
    int count = 1;
    ListNode node1= meetingNode.next;
    while (node1 != meetingNode) {
        node1 = node1.next;
        count++;
    }
    // 讓node1指針先走count步,node2再與node1一起走
    node1 = head;
    ListNode node2 = head;
    for (int i = 0;i < count;i++) {
        node1 = node1.next;
    }
    while (node1 != node2) {
        node1 = node1.next;
        node2 = node2.next;
    }
    // 相遇點即為環(huán)的入口節(jié)點
    return node1;
}

private ListNode getMeetingNode(ListNode head) {
    ListNode node1 = head;
    ListNode node2 = head;
    while (node1.next != null && node2.next != null) {
        node1 = node1.next;
        node2 = node2.next.next;
        if (node1 == node2) {
            return node1;
        }
    }
    return null;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末店读,一起剝皮案震驚了整個濱河市嗦枢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屯断,老刑警劉巖文虏,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異殖演,居然都是意外死亡氧秘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門趴久,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丸相,“玉大人,你說我怎么就攤上這事彼棍∶鹬遥” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵座硕,是天一觀的道長弛作。 經常有香客問我,道長坎吻,這世上最難降的妖魔是什么缆蝉? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮瘦真,結果婚禮上刊头,老公的妹妹穿的比我還像新娘。我一直安慰自己诸尽,他們只是感情好原杂,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著您机,像睡著了一般穿肄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上际看,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天咸产,我揣著相機與錄音,去河邊找鬼仲闽。 笑死脑溢,一個胖子當著我的面吹牛,可吹牛的內容都是我干的赖欣。 我是一名探鬼主播屑彻,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼顶吮!你這毒婦竟也來了社牲?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤悴了,失蹤者是張志新(化名)和其女友劉穎搏恤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體湃交,經...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡熟空,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了巡揍。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痛阻。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖腮敌,靈堂內的尸體忽然破棺而出阱当,到底是詐尸還是另有隱情,我是刑警寧澤糜工,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布弊添,位于F島的核電站,受9級特大地震影響捌木,放射性物質發(fā)生泄漏油坝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澈圈。 院中可真熱鬧彬檀,春花似錦、人聲如沸瞬女。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诽偷。三九已至坤学,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間报慕,已是汗流浹背深浮。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留眠冈,地道東北人飞苇。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像洋闽,于是被迫代替她去往敵國和親玄柠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內容