给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
不相交的情况
相交的情况
一个是另一个的一部分
思路1:
暴力求解(穷举法)
依次取A链表中的每个结点和B链表中的所有结点进行比较,如果有地址相同的结点,就是相交,第一个相交的点。时间复杂度是O(
N
2
N^2
N2)
思路2:
时间复杂度优化到O(N)
1.分别遍历两个链表,记住长度,如果两个链表的尾结点相同,则必然相交,否则不相交。
2.找交点:让长的链表先走(走长度差),然后两个一起走
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
if (headA == NULL)
{
return NULL;
}
if (headB == NULL)
{
return NULL;
}
struct ListNode* tailA = headA;
struct ListNode* tailB = headB;
int lenA = 0;
int lenB = 0;
while (tailA->next != NULL)
{
lenA++;
tailA = tailA->next;
}
while (tailB->next != NULL)
{
lenB++;
tailB = tailB->next;
}
if (tailA != tailB)
{
//不相交
return NULL;
}
//必然相交
//求交点
//长的先走
//方式1
//struct ListNode* curA = headA;
//struct ListNode* curB = headB;
//if (lenA > lenB)
//{
// //A先走
// int diff = lenA - lenB;
//
// while (diff > 0)
// {
// curA = curA->next;
// diff--;
// }
//}
//else
//{
// //B先走
// int diff = lenB - lenA;
// while (diff)
// {
// curB = curB->next;
// diff--;
// }
//}
一起走
//while (curA != curB)
//{
// //继续向后
// curA = curA->next;
// curB = curB->next;
//}
到达相交的结点
//return curA;
//方式2
int gap = abs(lenA - lenB);
//假设A是长的那个
struct ListNode* longList = headA;
struct ListNode* shortList = headB;
if (lenA < lenB)
{
//B是长的那个
longList = headB;
shortList = headA;
}
//长的先走gap
while (gap--)
{
longList = longList->next;
//gap--;
}
//一起走
while (longList != shortList)
{
//继续向后
longList = longList->next;
shortList = shortList->next;
}
//到达相交的结点
return longList;
}