求兩個連結串列的第一個公共結點(既求兩條單鏈表的交點)
阿新 • • 發佈:2018-12-10
題目:輸入兩條單鏈表
,求它們的第一個公共結點。結點的定義如下:
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;
}