劍指Offer:鏈表中環的入口節點

1. 如果鏈表中有環,可以通過快慢指針,最後快慢指針肯定會相會於環中的某個節點;

2. 從這個相會的節點開始,當再次遇到該節點,即可統計環中有節點數 n;

3. 設置兩個指針p,p1,p從頭先走 n 步,p1在頭部,然後兩個指針同時 走,當兩指針相遇時,相遇的節點即是環的入口。


C++ 代碼

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

ListNode* getMeetNode(ListNode* pHead) {// 用快慢指針,必然相會於環內某個節點,返回這個節點,否則返回 NULL
    if(NULL == pHead) return NULL;
    ListNode* pSlow = pHead->next;
    if(NULL == pSlow) return NULL;
    ListNode* pFast = pSlow->next;
    while(pSlow != NULL && pFast != NULL) {
        if(pFast == pSlow)
            return pFast;
        pFast = pFast->next;
        pSlow = pSlow->next;
        if(pFast != pSlow)
            pFast = pFast->next;
    }
    return NULL;
}

ListNode* EntryNodeOfLoop(ListNode* pHead) {
    ListNode* meetNode = getMeetNode(pHead);// 用快慢指針得到環內某個節點
    if(NULL == meetNode)
        return NULL;
    int n = 1;
    // 用這個環內節點計算得到環內節點數
    ListNode* p = meetNode->next;
    while(p != meetNode) {
        p = p->next;
        ++n;
    }
    // 用兩個指針,一個指針先走環內節點個數的步數,另一個節點在鏈表頭
    // 當兩個節點相遇時,此時的節點即是環的入口節點
    p = pHead;
    while(n--)
        p = p->next;
    ListNode* p1 = pHead;
    while(p1 != p) {
        p = p->next;
        p1 = p1->next;
    }
    return p;
}


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