利用两个链表交叉的性质,若两个链表交叉,那么从链表的交叉点到链表尾部,都是相同的节点。因此,链表的形状是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;
}
程序运行结果如下: