數據結構-劍指offer-鏈表中環的入口節點

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

思路:

1、確定一個鏈表中是否包含環。可以定義兩個指針,同時從鏈表的頭節點出發,一個指針一次走一步,另一個指針一次走兩步,如果走的快的指針追上了走的慢的指針,那麼鏈表就包含環;如果走的快的指針走到了鏈表的末尾,都沒有追上第一個指針,那麼鏈表就不包含環。

2、如何找到環的入口。分兩步進行:(1)判斷環中節點的數目;(2)找到環的入口。

(1)判斷環中節點的數目。在判斷一個鏈表裏是否有環時用到了一快一慢的兩個指針,如果兩個指針相遇,則表明鏈表中存在環,所以兩個指針相遇的節點一定是在環中!可以從這個相遇的節點出發,直到又回到這個節點,就可以得到環中節點數了。

(2)找到環的入口。如果鏈表中的環有n個節點,則指針P1先在鏈表上向前移動n步,然後兩個指針以相同的速度向前移動。當第二個指針指向環的入口節點時,第一個指針已經圍繞着環走了一圈,又回到了入口節點。

函數MeetingNode在鏈表存在環的前提下找到一快一慢兩個指針相遇的節點,函數EntryNodeOfLoop用來找環的入口節點。

class Solution {
private:
    ListNode* MeetingNode(ListNode* pHead){
        if(pHead == nullptr){
            return nullptr;
        }
        ListNode* pSlow = pHead->next;
        if(pSlow == nullptr){
            return nullptr;
        }
        ListNode* pFast = pSlow->next;
        while(pFast != nullptr && pSlow != nullptr){
            if(pFast == pSlow){
                return pFast;
            }
            pSlow = pSlow->next;
            pFast = pFast->next;
            if(pFast != nullptr){
                pFast = pFast->next;
            }
        }
        return nullptr;
    }
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead){
        ListNode* meetingNode = MeetingNode(pHead);
        if(meetingNode == nullptr){
            return nullptr;
        }
        int nodesInLoop = 1;
        ListNode* pNode1 = meetingNode;
        while(pNode1->next != meetingNode){
            pNode1 = pNode1->next;
            nodesInLoop++;
        }
        pNode1 = pHead;
        for(int i=0;i<nodesInLoop;i++){
            pNode1 = pNode1->next;
        }
        ListNode* pNode2 = pHead;
        while(pNode1 != pNode2){
            pNode1=pNode1->next;
            pNode2=pNode2->next;
        }
        return pNode1;
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章