有關鍊錶的經典面試題(二)

2021-08-09 10:12:34 字數 2900 閱讀 8625

1.判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?並計算每個演算法的時間複雜度&空間複雜度。

思路:利用快慢指標,快指標一次走兩步,慢指標一次走一步,如快慢指標有相遇點,則一定有環。找到相遇點後,求環長度問題,可以轉換為求頭結點到            相遇點之間的長度問題。求入口點時,讓快指標回到頭結點,兩指標再次相遇的點即入口點。

問題一:為什麼是乙個走一步,乙個走兩步?可不可以乙個走一步乙個走三步?

答:假設已經帶環,乙個跑快點,乙個跑慢點,那麼

進入環後,快的走兩步慢的走一步,每次可以縮短一步的距離,兩指標可以相遇。

而快的一次走3步,一次走四步就不一定了。(取決於慢指標進入環時與快指標的距離。如果只差一步,而快一次走3次的話,無法相遇。)

問題二:為什麼求環長度問題,可以轉換為求頭結點到相遇點之間的長度問題?

答:假設頭結點到環的入口點的距離為l,入口點到快慢指標相遇點的距離為x,環的長度為c,則有:

問題三:為什麼求環的入口點,可以轉換為求讓快指標回到頭結點後兩指標再次相遇的點?

答:假設頭結點到環的入口點的距離為l,入口點到快慢指標相遇點的距離為x,環的長度為c,則有:

本題的**為:

node* checkcycle(node* phead)  //判斷單鏈表是否帶環

}return null; //沒有環(fast可以走到null,或fast的下乙個為null) }

int lengthofcycle(node* phead, node* pos)  //若帶環,求環的長度,pos為相遇點

return length; }

node* findentry(node* phead)  //求環的入口點

}fast = phead;   //再讓快指標指向頭結點

while (fast != slow)  //兩指標都走一步,當兩指標在此相遇時,就是入口點

return fast; }

2.判斷兩個鍊錶是否相交,若相交,求交點。(假設鍊錶不帶環)

相交的三種情況:y  v  i  其中i有兩種情況,乙個是從頭就開始相交,乙個是第二個鍊錶就包含在公共節點鏈中。

判斷是否相交思路: 可對比兩鍊錶的最後乙個節點

求交點思路: 1.  兩個從頭出發,判斷兩個節點是否相等,不相等的話讓某一鍊錶的指標往後移,再對比判斷,不相等的話某鍊錶的指標再往後移,如果移到結尾也沒有相等,另乙個鍊錶的指標後移,再遍歷某煉表看是否有相等的點。第乙個相等點是交點。時間複雜度為:o(n)=t(n2)

2.因為相交之後的部分長度是相等的,所以我們先得到長鍊表長度和短鍊錶長度的差值。然後讓長鍊錶從頭走過相差的長度,之後再與短鍊錶同時向 後走。若遇到指標相等的點,該交點為兩鍊錶的交點。時間複雜度為o(n)=t(m+n)

3.讓第乙個鍊錶l1的尾節點指向另一鍊錶l2的頭結點,構成乙個環,則兩鍊錶的交點成為了環的入口點(整個l2在環內,以l1的頭結點來求入口點)。

最常用的是用第二種方法。

int iscrosswithoutcircle(node* phead1, node* phead2)    //判斷兩個不帶環鍊錶是否相交

while (tail1)

while (tail2)

return tail1 == tail2; }

node* getcrossnode(node* phead1, node* phead2)    //假設兩煉表不帶換環且相交,求兩鍊錶的交點

if (!iscrosswithoutcircle(phead1, phead2))    //先判斷是否有交點,若沒有,直接返回,不用再求交點

while (cur1)    //遍歷鍊錶1,求其長度

while (cur2)    //遍歷鍊錶2,求其長度

div = len1 - len2;   //求長鍊錶與短鍊錶的長度差值

cur1 = phead1;

cur2 = phead2;

if (div > 0)

}else

}while (cur1 != cur2)   //之後兩個指標一起走,直到相交

return cur1; }

測試**為:

void testlist6()

3.判斷兩個鍊錶是否相交,若相交,求交點(假設鍊錶可能帶環)

假設兩個鍊錶分別為l1和l2,根據兩個鍊錶的帶環情況來看相交的話,可能會出現的情況有以下幾種:

判斷是否相交思路: 因為兩個鍊錶都帶環且相交時會共用乙個環,所以在判斷相交與否時,可以找到兩個鍊錶的相遇點(判斷每個鍊錶是否帶環時快慢指標相遇的點),然後從任意乙個相遇點出發繞環一圈,若在此期間遇到了另乙個相遇點,則兩個帶環鍊錶相交。

求相交點思路: 對於環外相交,可以以任意乙個鍊錶的相遇點為尾,分別求兩個鍊錶從頭結點到該節點的距離,並讓長鍊表先走兩者長度差的距離,然後兩煉表再一起出發,直到遇到相等的節點,該節點為交點。

對於環內相交,其實整個換上都是兩鍊錶的交點。兩個較為特殊的點是兩個鍊錶的入口點,可任求乙個做交點。

int iscrosswithcircle(node* phead1, node* phead2)  //判斷鍊錶可能帶環時是否相交

else if(meet1 && meet2)  //兩鍊錶都帶環的情況

cur = cur->next; }

if (cur == meet2)    //出迴圈時少判斷了乙個節點,這裡補上

}return 0; }

有關鍊錶的經典面試題 (一)

1.比較順序表和煉表的優缺點,說說它們分別在什麼場景下使用?順序表 記憶體中位址連續,優點是隨機訪問比較便捷快速,建立也比較簡單,隨機查詢比較方便,可以直接給出下標,排序也方便 簡單。缺點 不夠靈活,刪除增加的工作量叫大,比較麻煩,長度不能實時變化 適用場景 適用於需要大量訪問元素的 而少量增添 刪...

和鍊錶有關面試題

面試中被問鍊錶的題目我就不再多說,直接總結題目。1 將鍊錶逆序 這個問題很早就研究過,但後來一次面試的時候我突然緊張忘了,沒答上來。我不知道大家的解法是什麼,我的解法是遍歷鍊錶是用前插發插入節點,最後的鍊錶就是逆序的。python view plain copy class listnode def...

有關鍊錶的面試題(再續)

今天讓我們來做一些複雜一些的鏈表面試題。1.複雜鍊錶的復刻。typedef struct cn cn cn copy cn pfirst 2.複製prandom。for pnode pfirst pnode null pnode pnode pnext pnext 3.拆鍊錶。for pnode p...