1. 程式人生 > >常見面試題解析-判斷是否有環

常見面試題解析-判斷是否有環

題目:假設我們有一個指標指向一個連結串列,並且我們知道這個連結串列是一個單鏈。能否在保證演算法的時間複雜度為O(n), 空間複雜度為O(1)的情況下,設計一種演算法判斷這個連結串列是否有環。

解析:這是個疑惑性很強的題目,無法根據直觀的想象得出答案。我們首先要考慮一下幾個因素:

1. 如果這個連結串列在單鏈的基礎上有環,那麼我們如果一直遍歷下去,肯定是沒有終止點的,而且會遍歷到之前的元素位置;

2. 我們僅有一個空間可以利用,那麼我們存放指標會比存放值資訊量更大;

3. 時間複雜度是n的情況下,我們的也只能使用單迴圈遍歷實現。


根據以上3點,我們可以確定這個題目要使用遍歷方法來完成,切一個額外的空間是用來存放指標。

我個人有兩種想法:

1. 我們把那個唯一的空間存放為第一個元素的指標,即當前連結串列指標的位置。然後連結串列指標以此往後迴圈,直到連結串列指標為NULL結束,如果遇到連結串列指標等於我們最初儲存的指標,說明有環。如果直到連結串列指標為NULL都沒有遇到相等的情況,則次連結串列沒有環。

bool CheckCircle(A* a)

{

    if(a == null || a ->next == null)

    {

        return false;

     }

    A* b = a;

    a = a->next;

    while(a != null)

    {

        if(a == b)

       {

           return ture;

       }

    }

    return false;

}


2. 使用模n演算法設定快慢指標,同樣要藉助連結串列有環的假設,如果連結串列中有話,我們採用模n演算法就可以得出結果了。

模n演算法原理:

n%n = 0;

2n%n = 0;

3n%n =0;

...

那麼我可以如果把唯一可以用的空間存為連結串列指標,用連結串列指標以此往後移動一個位置,而我們的臨時指標往後移動2個位置,那麼如果有環的話,移動n個位置後,兩個指標就會相等了。如果沒有環,則臨時指標會提前停止。

bool CheckCircle(A* a)

{

    if(a == null || a ->next == null)

    {

        return false;

     }

    A* b = a;

   while(b != null && b->next != null && b->next != null)

    {

       b = b->next->next;

       a = a->next;

        if(a == b)

       {

           return true;

       }

    }

    return false;

}


歡迎來參觀我的個人小站一折購(http://www.ezhegou.cn)