面試題 單鏈表中判斷是否有環以及得出環的入口點

2021-08-21 17:51:06 字數 2542 閱讀 5746

1.       判斷單鏈表是否有環

這是很多公司入門級的面試筆試題。單鏈表由於每個結點只有乙個next指標指向下乙個結點,不存在其他指標,所以一旦進入環裡,就再也出不去了。類似於下圖(像乙個烤盤)

那麼怎麼樣判斷單鏈表是否有環呢?方法很簡單,把環看作操場,兩位選手在操場上賽跑,乙個速度快,乙個速度慢,如果他們一直跑,快的選手肯定會在第一次超過慢的選手之後再次追上慢的選手,與他相遇;若現在沒有環,那麼快的選手將始終跑在慢的選手前面,不可能有第二次相遇。所以我們判斷乙個鍊錶是否有環的方法就是基於這個思想:

在鍊錶頭部設兩個指標,乙個每次向後移動兩個位置(快指標),另乙個每次向後移動乙個位置(慢指標)。這相當於在起點設定了兩位跑步選手,跑的快的選手的速度是慢的選手的兩倍。接下來兩個指標在遍歷鍊錶過程中,如果快指標到達鍊錶尾還沒有和慢指標相遇,說明鍊錶無環,反之說明有環。

2.       獲得環的入口點

書上說的公式挺複雜的,我們這裡只要考慮兩個指標第一次相遇的情況就好了。第一次相遇的條件是:快指標在環內比慢指標多走了一圈。如下圖所示,兩個指標從起點o出發,在環中的b點相遇,現在我們的目標是如何根據b點找到a點這個結點。注意:結點在環中的前進方向是順時針,即a→b→a.

毫無疑問,兩個指標第一次在b點相遇時:

慢指標走過的路程是:

s_slow = |oa| +|ab| = x + y.

快指標走過的路程是:

s_fast =  |oa| + |ab| + |ba| + |ab| = x + y + z + y.

又因為快指標的速度是慢指標的兩倍,所以在相同時間內快指標走過的路程是慢指標的兩倍,所以

s_fast = 2 * s_slow

即 2(x + y) = x + y + z + y.

求得 z = x.

所以說明

|ba| = |oa|.

所以在兩個指標相遇後,將慢指標移到o點起始位置,即煉表頭指標位置,快指標仍然在b點。然後它們一起向前移動,每次移動乙個位置,由於|ba| = |oa|, 所以他們最終肯定會在a點相遇,a點這個相遇點就是環的入口點。

具體實現**如下:

#include#includeusing namespace std;

typedef struct lnodelnode;

void createlistr(lnode *&head,int arr,int n);//尾插法建立帶頭結點的單向鍊錶

void showlist(lnode *head);

lnode * search(lnode *head,int x);

lnode *hascircal(lnode *head);//判斷是否有環,無返回nullptr,有則返回快慢結點相遇位址

lnode *findenter(lnode *head);//尋找環入口點位址

int main();

createlistr(head,arr,sizeof(arr)/sizeof(arr[0]));

showlist(head);

//構造乙個單向有環鏈表

lnode *p = search(head,112);//設定環入口點

lnode *end = search(head,126);

if(p != nullptr && end != nullptr)

end->next = p;

if(hascircal(head) != nullptr)

puts("有環");

else

puts("無環");

lnode *node = findenter(head);

if(node != nullptr)

printf("環入口結點為:%d\n",node->data);

else

puts("無環");

return 0;

}lnode *findenter(lnode *head)

return slow;

}lnode *hascircal(lnode *head)

return nullptr;

}lnode * search(lnode *head,int x)

p = p->next; }

return nullptr;

} void createlistr(lnode *&head,int arr,int n)//尾插法

} void showlist(lnode *head)

puts("");

}

面試題 判斷單鏈表是否有環

題目 如何在o 1 空間複雜度的條件下判斷單鏈表是否有環。思路 採用快慢指標,如果有環,兩指標一定會相遇。圖示 圖1 初始化情況,建立兩個指標都指向head節點。圖2 p指標為慢指標,每次只走一步 q指標為快指標,每次走兩步。圖3 p q繼續往後走。圖4 p q繼續往後走。圖5 p q繼續往後走。圖...

判斷單鏈表中是否有環

define crt secure no deprecate include include include include define ok 1 define error 0 define true 1 define false 0 typedef int status 函式結果狀態 如ok。t...

判斷單鏈表中是否有環

單鏈表中的迴圈鍊錶尾結點不一定指向頭結點,也可以指向任意中間結點。此時若想判斷單鏈表中是否有環,就不能只是簡單的根據尾結點的next是不是頭結點來判斷,在此我提供三種方法 方法一 建立兩個指標p和q,其中p用來遍歷指標,每次只走一步,並記錄從根節點出發所走的步數,而q則是每次從根節點出發,到達p此時...