1. 程式人生 > >劍指offer 連結串列中環的入口結點(詳細分析過程)

劍指offer 連結串列中環的入口結點(詳細分析過程)

思路:

題目描述

一個連結串列中包含環,請找出該連結串列的環的入口結點。來源:牛客網
兩個結論:        1、設定快慢指標,假如有環,他們最後一定相遇。        2、兩個指標分別從連結串列頭和相遇點繼續出發,每次走一步,最後一定相遇與環入口。
        證明1:設定快慢指標fast和low,fast每次走兩步,low每次走一步。假如有環,兩者一定會相遇(因為low一旦進環,可看作fast在後面追趕low的過程,每次兩者都接近一步,最後一定能追上)。        證明2:
        設:        連結串列頭到環入口長度為--a        環入口到相遇點長度為--b        相遇點到環入口長度為--c

        則:相遇時        快指標路程=a+(b+c)k+b ,k>=1  其中b+c為環的長度,k為繞環的圈數(k>=1,即最少一圈,不能是0圈,不然和慢指標走的一樣長,矛盾)。        慢指標路程=a+b        快指標走的路程是慢指標的兩倍,所以:        (a+b)*2=a+(b+c)k+b        化簡可得:        a=(k-1)(b+c)+c     這個式子的意思是:    連結串列頭到環入口的距離=相遇點到環入口的距離+(k-1)圈環長度。其中k>=1,所以k-1>=0圈。所以兩個指標分別從連結串列頭和相遇點出發,最後一定相遇於環入口。

程式碼:

class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        ListNode*fast=pHead,*low=pHead;
        while(fast&&fast->next){
            fast=fast->next->next;
            low=low->next;
            if(fast==low)
                break;
        }
        if(!fast||!fast->next)return NULL;
        low=pHead;
        while(fast!=low){
            fast=fast->next;
            low=low->next;
        }
        return low;
    }
};