利用兩個鏈表交叉的性質,若兩個鏈表交叉,那麼從鏈表的交叉點到鏈表尾部,都是相同的節點。因此,鏈表的形狀是Y型的。因爲是單鏈表,我們無法從鏈表尾部開始向前遍歷,找到第一個相同的節點。因此,我們可以先遍歷單鏈表1,計算出其長度len1,再遍歷單鏈表2,計算出長度len2,判斷哪個鏈表是長鏈表,哪個鏈表是短鏈表,我們記長鏈表的頭節點爲cur1,長度爲len1,短鏈表的頭節點爲cur2,長度爲len2。長鏈表中,先從頭節點cur1往後走(len1 - len2)步,然後同時開始往後遍歷兩個鏈表,每當遍歷一個節點時,比較cur1和cur2是否相等,若相等則表示兩個鏈表是交叉的,若將兩個鏈表遍歷完之後,仍未找到相同的節點,那麼表面這兩個鏈表沒有交叉。
代碼如下:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct listNode
{
int val;
struct listNode *next;
};
listNode *isIntersect(listNode *head1, listNode *head2)
{
if (head1 == NULL || head2 == NULL)
{
return NULL;
}
listNode *cur1 = head1;
listNode *cur2 = head2;
// 求單鏈表1的長度len1
int len1= 0, len2 = 0;
while(cur1 != NULL)
{
++len1;
cur1 = cur1->next;
}
cur1 = head1;
// 求單鏈表2的長度len2
while(cur2 != NULL)
{
++len2;
cur2 = cur2->next;
}
cur2 = head2;
// 長鏈表頭節點爲cur1,長度爲len1,短鏈表頭節點爲cur2,長度爲len2
if (len1 < len2)
{
int tmp = len1;
len1 = len2;
len2 = tmp;
listNode *temp = cur1;
cur1 = cur2;
cur2 = temp;
}
// 判斷兩鏈表是否交叉
int diff = len1 - len2;
while (diff--)
{
cur1 = cur1->next;
}
while(cur1 != NULL && cur2 != NULL)
{
if (cur1 == cur2)
{
return cur1;
}
cur1 = cur1->next;
cur2 = cur2->next;
}
return NULL;
}
int main()
{
// 先建立一個有11個節點的單鏈表:0-1-2-3-4-5-6-7-8-9-10
listNode *head1 = new listNode;
head1->val = 0;
int n = 0;
listNode *cur1 = head1;
while(++n <= 10)
{
cur1->next = new listNode;
cur1 = cur1->next;
cur1->val = n;
}
cur1->next = NULL;
cur1 = head1;
n = 0;
while(++n <= 5)
{
cur1 = cur1->next;
}
// 單鏈表2: -1,-1,-2,-3,-4,-5,5,6,7,8,9,10
listNode *head2 = new listNode;
head2->val = -1;
n = 0;
listNode *cur2 = head2;
while (++n <=5)
{
cur2->next = new listNode;
cur2 = cur2->next;
cur2->val = -n;
}
cur2->next = cur1;
cur1 = head1;
cur2 = head2;
// 分別打印兩單鏈表的節點地址
cout << "單鏈表1的節點地址爲:";
while(cur1 != NULL)
{
cout << cur1 << " ";
cur1 = cur1->next;
}
cout << endl;
cout << "單鏈表2的節點地址爲:";
while(cur2 != NULL)
{
cout << cur2 << " ";
cur2 = cur2->next;
}
cout << endl;
listNode *result = isIntersect(head1, head2);
cout << "兩個鏈表的交叉節點地址爲" << result << endl;
return 0;
}
程序運行結果如下: