我們學乙個演算法,一定是為了用吧,所謂「學以致用」嗎?那麼判斷兩個鍊錶是否相交有什麼用呢?這是因為一旦兩個鍊錶出現相交的情況,就可能發生這樣的情況,程式釋放了鍊錶la的所有節點,這樣就導致了另外乙個與之有相交節點的鍊錶lb中的節點也釋放了,而lb的使用者,可能並不知道事實的真相,這會帶來很大的麻煩。
1.問題分析
看看兩個鍊錶相交到底是怎麼回事吧,有這樣的的幾個事實:(假設鍊錶中不存在環)
(1)一旦兩個鍊錶相交,那麼兩個鍊錶中的節點一定有相同位址。
(2)一旦兩個鍊錶相交,那麼兩個鍊錶從相交節點開始到尾節點一定都是相同的節點。
分析出來了問題的本質,那麼思路也就自然有了。
2.問題解法
2.1 雜湊解法:
既然連個鍊錶一旦相交,相交節點一定有相同的記憶體位址,而不同的節點記憶體位址一定是不同的,那麼不妨利用記憶體位址建立雜湊表,如此通過判斷兩個鍊錶中是否存在記憶體位址相同的節點判斷兩個鍊錶是否相交。具體做法是:遍歷第乙個鍊錶,並利用位址建立雜湊表,遍歷第二個鍊錶,看看位址雜湊值是否和第乙個表中的節點位址值有相同即可判斷兩個鍊錶是否相交。
時間複雜度o(length1 + length2)
空間複雜度o(length1)
分析:時間複雜度是線性的,可以接受,並且可以順便找到第乙個相交節點,但是卻增加了o(length1)的空間複雜度,這顯然不能令人滿意。
2.2 問題轉化
如果兩個鍊錶中存在相交節點,那麼將第二個鍊錶接到第乙個鍊錶的後面,然後從第二個鍊錶的表頭開始遍歷,如果存在環,則遍歷過程一定會回到鍊錶二的表頭節點。可是這種方法似乎並不能找到第乙個相交節點。怎麼辦呢?怎樣才能判斷鍊錶中是否存在環,並且找到環的開始節點呢?
網上看到了這樣的乙個解法:設定兩個指標fast和slow,初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。(當然,fast先行頭到尾部為null,則為無環鏈表),這樣就可以判斷兩個鍊錶是否相交了,程式如下:
bool i***itsloop(slist *head)
return !(fast == null || fast->next == null);
}
下面看看怎麼找環的入口,當fast與slow相遇時,slow肯定沒有走遍歷完鍊錶,而fast已經在環內迴圈了n圈(1<=n)。假設slow走了s步,則fast走了2s步(fast步數還等於s 加上在環上多轉的n圈),設環長為r,則:
2s = s + nr
s= nr
設整個鍊錶長l,入口環與相遇點距離為x,起點到環入口點的距離為a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + l - a
a = (n-1)r + (l – a – x)
(l – a – x)為相遇點到環入口點的距離,由此可知,從煉表頭到環入口點等於(n-1)迴圈內環+相遇點到環入口點(從相遇點向後遍歷迴圈回到入口點的距離),於是我們從煉表頭、與相遇點分別設乙個指標,每次各走一步,兩個指標必定相遇,且相遇點為環入口點,也即為兩個鍊錶的第乙個相同節點。程式描述如下:
slist* findloopport(slist *head)
if (fast == null || fast->next == null)
return null;
slow = head;
while (slow != fast)
return slow;
}
這種解法似乎是非常犀利,邏輯推理很棒,但是這種解法的時間複雜度是怎麼樣的呢??slow每次前進一步,fast每次前進兩步,這樣的話遍歷多少步會結束呢???(求人解釋)
2.3 抓住要點
不妨遍歷每個鍊錶儲存最後乙個節點,看看最後乙個節點是否是同乙個節點,這種情況時間複雜度是o(length1 + length2)。基本也不需要什麼空間,似乎是乙個不錯的想法哦,那麼怎麼找到第乙個相交節點呢?可以遍歷的過程中記錄鍊錶的長度l1和l2(假設l1>l2)這是遍歷找到第乙個鍊錶中的第l1 - l2節點,然後鍊錶一從第l1-l2個節點開始遍歷,鍊錶二從第乙個節點遍歷,每次前進一步,直到找到第乙個相同的節點,則可以認為兩個鍊錶存在相交節點,並且該點即為第乙個相交節點(原來這裡寫錯了,感謝ider指出這個錯誤)。這種解法的時間複雜度也是線性的,但是如果兩個鍊錶長度相差不多時,時間複雜度還是不錯的。
到這裡,我知道的幾種典型的解法就說完了。歡迎大神們提供新的思路!!
3.問題擴充套件:(思考)
baidu曾經出過這樣的乙個筆試題目,歸根到底也是找到兩個鍊錶是否存在相同的節點,但是資料量很大,即鍊錶長度是上億的。想想那麼應該怎麼處理呢?
如何判斷兩個鍊錶相交及找到第乙個相交點
我們學乙個演算法,一定是為了用吧,所謂 學以致用 嗎?那麼判斷兩個鍊錶是否相交有什麼用呢?這是因為一旦兩個鍊錶出現相交的情況,就可能發生這樣的情況,程式釋放了鍊錶la的所有節點,這樣就導致了另外乙個與之有相交節點的鍊錶lb中的節點也釋放了,而lb的使用者,可能並不知道事實的真相,這會帶來很大的麻煩。...
如何判斷兩個鍊錶相交及找到第乙個相交點
1.暴力解法。從頭開始遍歷第乙個鍊錶,遍歷第乙個鍊錶的每個節點時,同時從頭到尾遍歷第二個鍊錶,看是否有相同的節點,第一次找到相同的節點即第乙個交點。若第乙個鍊錶遍歷結束後,還未找到相同的節點,即不存在交點。時間複雜度為o n 2 這種方法顯然不是寫這篇部落格的重點。不多說了。2.使用棧。我們可以從頭...
如何判斷兩個鍊錶相交及找到第乙個相交點
如何判斷兩個鍊錶相交及找到第乙個相交點 1.問題分析 看看兩個鍊錶相交到底是怎麼回事吧,有這樣的的幾個事實 假設鍊錶中不存在環 1 一旦兩個鍊錶相交,那麼兩個鍊錶中的節點一定有相同位址。2 一旦兩個鍊錶相交,那麼兩個鍊錶從相交節點開始到尾節點一定都是相同的節點。分析出來了問題的本質,那麼思路也就自然...