判断两个链表是否相交,若相交,求交点:
如图所示:
1,直接把两个链表的每一个节点都遍历一遍,时间复杂度:O(len1*len2)。
2,hash计数法:两个链表相交,则两个链表就会由共同的节点,而节点地址又是唯一的标识,所以判断两个链表中是否存在地址一致的节点就可以判断出是否相交。可以对第一个链表的节点地址进行hash排序,建立hash表,然后对第二个链表的每一个节点地址查询hash表,如果有节点在第一个链表所建立的hash表中表现出来,那么就说明两个链表相交,但是这个方法有不好的地方:时间复杂度:O(max(len1+len2)),并且同时还得增加O(len1)的存储空间来存储哈希表。
3,如图所示,如果两个链表相交,那么在相交之后的多有节点都是两个链表共享的,那么我们只需要判断最后一个节点是否相同就好了。时间复杂度是:O(len1+len2)。对于相交后的第一个节点,则可以求出两个链表的长度,然后用长的减去短的得到一个插值K,然后先让长的链表先遍历K个节点,然后两个链表再开始比较。还可以这样:其中一个链表首尾相连,检测另一个链表是否存在,如果存在,则两个链表相交,而检测出来的依赖环入口即为相交的第一个。
代码的实现:
#include<iostream>
#include<math.h>
using namespace std;
typedef struct node_t
{
int data;
struct node_t *next;
}node;
node *find_node(node *head1, node *head2)
{
if (NULL == head1 || NULL == head2)
{
return NULL;//如果有为空的链表,肯定是不相交的
}
node *p1, *p2;
p1 = head1;
p2 = head2;
int len1 = 0;
int len2 = 0;
int diff = 0;
while (NULL != p1->next)
{
p1 = p1->next;
len1++;
}
while (NULL != p2->next)
{
p2 = p2->next;
len2++;
}
if (p1 != p2) //如果最后一个节点不相同,返回NULL
{
return NULL;
}
diff = abs(len1 - len2);
if (len1 > len2)
{
p1 = head1;
p2 = head2;
}
else
{
p1 = head2;
p2 = head1;
}
for (int i = 0; i<diff; i++)
{
p1 = p1->next;
}
while (p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}