小白算法積累——單鏈表8#兩個單鏈表的公共節點

題目:給定兩個單鏈表,編寫算法找出兩個鏈表的公共結點

關鍵字:兩個鏈表+查找公共節點

思路
兩個單鏈表有公共節點,意味着:兩個鏈表從某一結點開始,它們的next都指向同一個結點。由於每個單鏈表結點只有一個next域,因此從第一個公共結點開始,之後它們所有的結點都是重合的,不可能再出現分叉。
所以,兩個有公共結點而部分重合的單鏈表,拓撲形狀看起來像Y,而不可能像X

“低級思路”:在第一個鏈表上順序遍歷每個結點,每遍歷一個結點,在第二個鏈表上順序遍歷所有結點,若找到兩個相同的結點,則找到了它們的公共結點。顯然,改算法的時間複雜度爲O(len1*len2)

“高級思路”:
先把問題簡化(從結果倒退尋找線索):
首先,最基本的底層問題,
Q:如何判斷兩個單向鏈表有沒有公共結點?
A:若某點爲兩個鏈表的公共結點,那麼,該公共結點之後所有的結點都是重合的,所有它們的最後一個結點必然是重合的。

因此,判斷兩個單鏈表是否有公共結點的核心,就是判斷兩個鏈表的尾結點是否一樣。
如果尾結點一樣,則它們有公共節點。
否則,它們一定沒有公共結點。

然鵝,在上面的思路中,順序表遍歷兩個鏈表到尾結點時,並不能保證在兩個鏈表上同時到達尾結點。
這是因爲兩個鏈表長度不一定一樣。
Q:如何解決兩個鏈表同時掃描到首個公共結點呢?
A:假設一個鏈表比另一個長k個結點,我們先在長的鏈表上遍歷k個結點,之後再同步遍歷。
此時我們就能保證同時到達最後一個結點。
由於兩個鏈表從第一個公共結點開始到鏈表的尾結點,這一部分是重合的,
因此它們肯定也是同時到達第一公共結點的。
於是在遍歷中,第一個相同的結點就是第一個公共的結點。

具體步驟:`
1.分別遍歷兩個鏈表得到它們的長度,並求出兩個長度之差。
需要變量:L1,L2 ,
兩個表各自的長度; len1,len2
各自的指針LinkList longlist,shortlist

2.在長的鏈表上先遍歷長度之差個結點之後,再同步遍歷兩個鏈表,
直到找到相同的結點,或者一直到鏈表結束
需要變量:長度之差:dist
此時時間複雜度爲O(len1+len2),高效了很多。

LinkList Search_1st_Common(LinkList L1,LinkList L2){//本算法實現在線性的時間內找到兩個單鏈表的第一個公共結點
     int len1=Length(L1),len2=Length(L2);//計算兩個鏈表的表長
     LinkList longList,shortList;//分別指向表長較長和較短的鏈表
     if(len1>len2){//當L1表長較長
     longList=L1->next;shortList=L2->next;
     dist=len1-len2;//表長之差
    }
    else
      longList=L2->next;shortList=L1->next;//L2表長較長
      dist=len2-len1;//表長之差
    }
    while(dist--)//較長的鏈表先遍歷到第dist個結點
        longList=longList->next;
    while(longList!=NULL){//開始同步遍歷,尋找共同結點
       if(longList==shortList)//找到第一個公共結點
         return longList;
       else{//繼續同步尋找
           longList=longList->next;
           shortList=shortList->next;
         }
       }
       return NULL;
     }
      
}
     


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