一個鏈表中包含環,請找出該鏈表的環的入口結點。


  如果一個鏈表中有環,那么,我們如何找到這個鏈表的入口節點呢? 

  思路是這樣的:設定兩個指針,一個慢指針,一個快指針,快指針的速度是慢指針的兩倍,然后呢,如果有環,他們一定會在環中相遇。 

 (1) 如果這時快指針已經是在環里走了一圈了(這種情況對應於非環指針較短的情況),如下所示:

    

  根據上圖,我們可以得到下面的關系式:

  • w + n + y = 2 (w + y)

   經過化簡,我們可以得到:w  = n - y;

  

      所以,這種情況下,我們就可以直接把p2放在pHead處,然后讓兩個指針以同樣的速度走,那么,兩者下一次就一定在入口節點相遇了。

 

  (2)如果是相遇的時候,p2已經走了很多圈了,思路也是一樣的,只是這時的w會更長一點,並且我們可以肯定的是p1肯定不會繞着圈走一圈,即p1只在環上走了y的距離:

  • w + y + kn = 2 (w + y) 

  同樣,我們可以推到出來, kn - y = w。 

  然后,這時還是可以將P2放在pHead處,p1在轉了n圈之后,也一定會在入口節點和剛剛到來的p2相遇。 

 

   所以, 最終代碼如下所示:

/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
    // write code here
    // 使用兩個指針,一個快的,一個慢的,快的時慢的兩倍,如果有環,那么他么一定會相遇。
    if (pHead == null || pHead.next == null) {
        return null;
    }
    
    var p1 = pHead;
    var p2 = pHead;
    while (p2 != null && p2.next != null) {
        p1 = p1.next;
        p2 = p2.next.next;
        if (p1 == p2) {
            p2 = pHead;
            while (p1 != p2) {
                p1 = p1.next;
                p2 = p2.next;
            }
            if (p1 == p2) {
                return p1;
            }
        }
    }
    return null;
    
}
module.exports = {
    EntryNodeOfLoop : EntryNodeOfLoop
};

 

題目鏈接

 

 

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM