劍指Offer——鏈表中環的入口結點

題目描述

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

方法一:

對鏈表進行遍歷,利用set等結構,將已經遍歷過的節點存入set,每遍歷一個節點,判斷set中是否已經存在該節點,如果存在,那麼說明鏈表存在環,且該節點就是入口節點,返回該節點;如果遍歷到NULL,說明已經到了鏈表結尾,說明該鏈表不存在環,返回NULL。

代碼

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if( pHead == NULL || pHead->next == NULL )
            return NULL;
         
        unordered_set<ListNode*> s;
        ListNode* p = pHead;
        while( p )
        {
            if( s.find(p) != s.end() )
                return p;
            s.insert(p);
            p = p->next;
        }
        return NULL;
    }
};

方法二:

分爲兩步:判斷是否存在環,找到環的入口節點

1、判斷是否存在環:利用兩個指針,同時從鏈表的頭節點出發,一個指針一次走一步,另一個指針一次走兩步,如果兩個指針相遇,則存在環;如果兩個指針中任意一個等於NULL,說明不存在環。可以將相遇時的指針返回,後面會用到。

2、找環的入口:

首先判斷環中節點個數,利用前面找到的相遇時的節點,該節點一定是在環中的,可以從該節點出發,一邊向前一邊計數,再次回到該節點時,就可以得到環中節點個數n了。

建立兩個指針p1和p2,令p1先走n不,然後p1和p2以相同速度向前移動,直到他們相遇,他們相遇的節點就是環的入口,如下圖所示


代碼

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if( pHead == NULL || pHead->next == NULL )
            return NULL;
         
        ListNode* meetingNode = MeetingNode(pHead);
        if( meetingNode == NULL )
            return NULL;
         
        ListNode* p = meetingNode->next;
        int count = 0;
        while( p != meetingNode )
        {
            count++;
            p = p->next;
        }
        p = pHead;
        for( int i=0;i<=count;i++ )
            p = p->next;
        ListNode* p2 = pHead;
        while( p != p2 )
        {
            p = p->next;
            p2 = p2->next;
        }
        return p;
    }
     
    ListNode* MeetingNode(ListNode* pHead)
    {
        ListNode* p1 = pHead->next;
        ListNode* p2 = pHead->next->next;
         
        while( p1 != NULL && p2 != NULL )
        {
            if( p1 == p2 )
                return p1;
            p1 = p1->next;
            p2 = p2->next;
            if( p2 != NULL )
                p2 = p2->next;
            else
                return NULL;
        }
        return NULL;
    }
};
發佈了52 篇原創文章 · 獲贊 54 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章