常見面試題解析-判斷是否有環
題目:假設我們有一個指標指向一個連結串列,並且我們知道這個連結串列是一個單鏈。能否在保證演算法的時間複雜度為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)