經典面試題17 - 搜索編程判斷兩個鏈表是否相交

問題
給出兩個單向鏈表的頭指針(如下圖所示),


比如h1、h2,判斷這兩個鏈表是否相交。這裏爲了簡化問題,我們假設兩個鏈表均不帶環。

解答

  • 直接循環判斷第一個鏈表的每個節點是否在第二個鏈表中。但這種方法的時間複雜度爲O(Length(h1) * Length(h2))。顯然,我們得找到一種更爲有效的方法,至少不能是O(N^2)的複雜度。

  • 針對第一個鏈表直接構造hash表,然後查詢hash表,判斷第二個鏈表的每個節點是否在hash表出現,如果所有的第二個鏈表的節點都能在hash表中找到,即說明第二個鏈表與第一個鏈表有相同的節點。時間複雜度爲爲線性:O(Length(h1) + Length(h2)),同時爲了存儲第一個鏈表的所有節點,空間複雜度爲O(Length(h1))。

  • 轉換爲環的問題。把第二個鏈表接在第一個鏈表後面,如果得到的鏈表有環,則說明兩個鏈表相交。如何判斷有環的問題上面已經討論過了,但這裏有更簡單的方法。因爲如果有環,則第二個鏈表的表頭一定也在環上,即第二個鏈表會構成一個循環鏈表,我們只需要遍歷第二個鏈表,看是否會回到起始點就可以判斷出來。這個方法的時間複雜度是線性的,空間是常數。

  • 進一步考慮“如果兩個沒有環的鏈表相交於某一節點,那麼在這個節點之後的所有節點都是兩個鏈表共有的”這個特點,我們可以知道,如果它們相交,則最後一個節點一定是共有的。而我們很容易能得到鏈表的最後一個節點,所以這成了我們簡化解法的一個主要突破口。那麼,我們只要判斷兩個鏈表的尾指針是否相等。相等,則鏈表相交;否則,鏈表不相交。
    所以,先遍歷第一個鏈表,記住最後一個節點。然後遍歷第二個鏈表,到最後一個節點時和第一個鏈表的最後一個節點做比較,如果相同,則相交,否則,不相交。這樣我們就得到了一個時間複雜度,它爲O((Length(h1) + Length(h2)),而且只用了一個額外的指針來存儲最後一個節點。這個方法時間複雜度爲線性O(N),空間複雜度爲O(1),顯然比解法三更勝一籌。

/判斷兩個鏈表是否相交
bool isIntersect(Node *h1,Node *h2)
{
  //異常判斷
    if(h1 == NULL || h2 == NULL) return false;    
    while(h1->next != NULL) {
        h1 = h1->next;
    }
    while(h2->next != NULL) {
        h2 = h2->next;
    }
    //尾節點是否相同
    if(h1 == h2) return true;        
    else return false;
}

更多閱讀
經典面試100題 - 持續更新中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章