1. 程式人生 > >求兩個連結串列的第一個公共結點(既求兩條單鏈表的交點)

求兩個連結串列的第一個公共結點(既求兩條單鏈表的交點)

題目:輸入兩條單鏈表,求它們的第一個公共結點。結點的定義如下:

typedef struct Node
{
    DataType data;
    struct Node* next;
}Node,*pLinkList;

解題思路:

  • 方法一:暴力法。拿出一條連結串列中的一個結點,然後在另一條連結串列中從前向後掃描,如果存在相同的結點,則此節點為第一個公共結點,否則,繼續向後遍歷。假設兩條連結串列的長度,一條為m,一條為n。這種方法的時間複雜度為O(m*n)

  • 方法二:藉助棧的後進先出特點。兩條單鏈表相交會有什麼特點?它們相交後最後一個結點一定是同一個結點,可能是Y或者>

    ,但是絕對不可能是X。既然是這樣,我們能不能考慮從連結串列的最後,向前開始遍歷呢?如果最後兩條連結串列的最後一個結點相同,則繼續向前找有沒有相同的結點,如果沒有,則這個結點就是第一個公共結點,如果有,則繼續向前找。對於單鏈表,我們是沒有辦法從前向後遍歷的,所以只能藉助於棧,遍歷兩條連結串列,將他們分別壓入一個棧,我們只要從棧頂開始比較即可。假設兩條連結串列的長度,一條為m,一條為n。這種方法的時間複雜度為O(m+n),空間複雜度也是O(m+n),所以這是一種用空間換取時間的方法。

  • 方法三:快慢指標的思想。我們可以先求出兩個連結串列的長度差,然後讓長的那條連結串列先走長度差步,然後兩條連結串列一起走,他們一定會在第一個公共結點處相遇。這種方法的時間複雜度為O(n+m)

    ,但是空間複雜度卻為O(1)

由於前兩種辦法的時間複雜度或空間複雜度較高,面試官一般不會喜歡,所以這裡只實現第三種方法:快慢指標的思想

程式碼實現:

//求兩條連結串列的第一個公共結點
Node* GetMeetNode(pLinkList plist1, pLinkList plist2)
{
    int len1 = 0;
    int len2 = 0;
    int gap = 0;
    Node* cur1 = plist1;
    Node* cur2 = plist2;
    //求連結串列1長度
    while (cur1)
    {
        len1++
; cur1 = cur1->next; } //求連結串列2長度 while (cur2) { len2++; cur2 = cur2->next; } //求差值 gap = abs(len1 - len2); cur1 = plist1;//長 cur2 = plist2;//短 if (len1 < len2) { cur1 = plist2; cur2 = plist1; } //較長連結串列先走gap步 while (gap--) { cur1 = cur1->next; } //兩個指標一起走一起走 while (cur1!=cur2) { cur1 = cur1->next; cur2 = cur2->next; } return cur1; }