程式設計師面試題精選 找出兩個鍊錶的第乙個公共節點

2021-05-25 13:01:57 字數 1119 閱讀 6416

問題描述:給定兩個單向鍊錶,找出它們的第乙個公共節點。鍊錶的節點定義如下:

struct listnode

int       m_nkey;

listnode*   m_pnext;

問題分析:這是一道微軟的面試題。微軟非常喜歡與鍊錶相關的題目,因此在微軟的面試題中,鍊錶出現的概率非常高。如果兩個單向鍊錶有公共的節點,也就是說兩個鍊錶從某乙個節點開始,它們的m_pnext都指向同乙個節點。但由於是單向鍊錶的節點,每個節點只有乙個m_pnext,因此從第乙個公共節點開始,之後它們所有的節點都是重合的,不可能出現分叉。所以,兩個有公共結點而部分重合的鍊錶,拓撲形狀看起來像乙個y

,而不可能像x。

看到這個題目,第一反應就是蠻力法:在第一鍊錶上順序遍歷每個結點。每遍歷乙個結點的時候,在第二個鍊錶上順序遍歷每個結點。如果此時兩個鍊錶上的結點是一樣的,說明此時兩個鍊錶重合,於是找到了它們的公共結點。如果第乙個鍊錶的長度為

m,第二個鍊錶的長度為

n,顯然,該方法的時間複雜度為

o(mn)

。接下來我們試著去尋找乙個線性時間複雜度的演算法。我們先把問題簡化:如何判斷兩個單向鍊錶有沒有公共結點?前面已經提到,如果兩個鍊錶有乙個公共結點,那麼該公共結點之後的所有結點都是重合的。那麼,它們的最後乙個結點必然是重合的。因此,我們判斷兩個鍊錶是不是有重合的部分,只要分別遍歷兩個鍊錶到最後乙個結點。如果兩個尾結點是一樣的,說明它們重合;否則兩個鍊錶沒有公共的結點。

在上面的思路中,順序遍歷兩個鍊錶到尾結點的時候,我們不能保證在兩個鍊錶上同時到達尾結點。這是因為兩個鍊錶長度不一定一樣。但我們假設乙個鍊錶比另乙個長

l個結點,我們先在長的鍊錶上遍歷

l個結點,之後再同步遍歷兩個鍊錶,這個時候我們就能保證兩個鍊錶同時到達尾節點了。由於兩個鍊錶從第乙個公共結點開始到鍊錶的尾結點,這一部分是重合的。因此,它們肯定也是同時到達第一公共結點的。於是在遍歷中,第乙個相同的結點就是第乙個公共的結點。

在這個思路中,我們先要分別遍歷兩個鍊錶得到它們的長度,並求出兩個鍊錶的長度之差。在長的鍊錶上先遍歷若干次之後,再同步遍歷兩個鍊錶,直到找到相同的結點,或者一直到鍊錶結束。此時,如果第乙個鍊錶的長度為

m,第二個鍊錶的長度為

n,該方法的時間複雜度為

o(m+n)

。實現演算法如下:

程式設計師面試題精選

問題描述 輸入乙個字串,列印出該字串中字元的所有排列。例如輸入字串abc,則輸出由字元a b c所能排列出來的所有字串abc acb bac bca cab和cba。問題分析 這是一道很好的考查對遞迴理解的程式設計題。寫遞迴程式關鍵有兩點,處理好進入與返回的關係,進入時改變了什麼,返回時應當恢復。字...

程式設計師面試題精選(18) 用兩個棧實現佇列

題目 某佇列的宣告如下 template class cqueue cqueue void deletehead remove a element from head private t m stack1 t m stack2 分析 從上面的類的宣告中,我們發現在佇列中有兩個棧。因此這道題實質上是要...

程式設計師面試題精選 18 用兩個棧實現佇列

題目 某佇列的宣告如下 分析 從上面的類的宣告中,我們發現在佇列中有兩個棧。因此這道題實質上是要求我們用兩個棧來實現乙個佇列。相信大家對棧和佇列的基本性質都非常了解了 棧是一種後入先出的資料容器,因此對佇列進行的插入和刪除操作都是在棧頂上進行 佇列是一種先入先出的資料容器,我們總是把新元素插入到佇列...