鏈表帶環問題【每日一題】

1.如何判斷是否有環?
與返回鏈表倒數第k個節點的問題類似,定義兩個結點指針,一個走的快,一個走的慢,那麼當快的那個指針追上慢的指針時,說明鏈表帶環。

2.如何計算環的長度?
從第一次相遇(超一圈)時開始計數,第二次相遇時停止計數,返回的這個計數即爲環的長度。

3.如何判斷環的入口點:碰撞點到連接點的距離等於頭指針到連接點的距離,因此,分別從碰撞點、頭指針開始走,相遇的那個點就是連接點。

上述是一個簡單的計算過程:
(1)當fast與slow相遇時,show肯定沒有走完鏈表,而fast已經在還裏走了n(n>= 1)圈。假設slow走了s步,那麼fast走了2s步。fast的步數還等於s走的加上環裏轉的n圈,所以有:2s = s + nr。因此,s = nr。
(2)設整個鏈表長爲L,入口據相遇點X,起點到入口的距離爲a。因爲slow指針並沒有走完一圈,所以:
a + x = s,帶入第一步的結果,有:a + x = nr = (n-1)r + r = (n-1)r + L - a;即:a = (n-1)r + L -a -x;

//判斷鏈表是否帶環
int isLoop(PNode pHead)
{
    PNode fast = pHead;
    PNode slow = pHead;
    while(fast != NULL && fast->_pNext != NULL)
    {
        fast = fast->_pNext ->_pNext ;
        slow = slow->_pNext ;

        if(fast == slow)
            break;
    }
    if(fast == NULL || fast->_pNext == NULL)
        return 0;
    else
        return 1;
} 
//計算環的長度
int loopLength(PNode pHead)
{
    if(!isLoop(pHead))
        return 0;
    PNode fast = pHead;
    PNode slow = pHead;
    int length = 0;
    int flag1 = 0;
    int flag2 = 0;
    while(fast != NULL && fast->_pNext != NULL)
    {
        fast = fast->_pNext ->_pNext ;
        slow = slow->_pNext ;
        if(fast == slow && !flag2)
            break;
        if(fast == slow && flag2)
        {
            flag1 = 1;
            flag2 = 1;
        }
        if(flag1)
            ++length;
    }
    return length;
}
//找到環的入口
Node* findLoopEntrance(PNode pHead)
{
    PNode fast = pHead;
    PNode slow = pHead;
    while(fast != NULL && fast->_pNext != NULL)
    {
        fast = fast->_pNext ->_pNext ;
        slow = slow->_pNext ;
        if(fast == slow)
            break;
    }
    if(fast == NULL || fast->_pNext == NULL)
        return NULL;
    slow = pHead;
    while(slow != fast)
    {
        slow = slow->_pNext ;
        fast = fast->_pNext ;
    }
    return slow;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章