如果一個鏈表中有環,那么,我們如何找到這個鏈表的入口節點呢?
思路是這樣的:設定兩個指針,一個慢指針,一個快指針,快指針的速度是慢指針的兩倍,然后呢,如果有環,他們一定會在環中相遇。
(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 };