题目描述
描述
编写一个程序,找到两个单链表相交的起始结点。
在结点c1开始相交(单链表不存在交叉,但存在相交)
当相交时,返回结点所在的值,不相交时返回null。在返回结果后,两个链表仍须保持原有的结构
可假定整个链表结构中没有循环。程序尽量满足O(n)时间复杂度,且仅用O(1)内存。
解题分析:
思路1:
用A链表的每一个结点的地址和B链表中的所有节点的地址比较,如果存在地址相同,则相交。并返回第一个相交的结点。
时间复杂度为O(M*N)
思路2:尾节点相同就是相交,否则就不相交,并求相交结点。
判断相交:分别遍历两个链表,判断最后一个结点的地址是否相同。
求相交结点:如果两个链表长度不同,则先让长的链表走长度差L1-L2步,再两个链表同时走。当两个结点相同时,结束并返回相交的结点。
代码实现2:
struct ListNode
{
int val;
struct ListNode* next;
};
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
if (headA == NULL || headB == NULL)
{
return NULL;
}
//1、判断是否相交
//定义两个变量存放头结点来操作,防止迭代时头结点的值改变
struct ListNode* tailA = headA;
struct ListNode* tailB = headB;
//2、计算两个链表的长度
int lenA = 1;//这是从1开始
int lenB = 1;
while (tailA->next != NULL)
{
lenA++;
tailA = tailA->next;
}
while (tailB->next != NULL)
{
lenB++;
tailB = tailB->next;
}
if(tailA != tailB)
{
return NULL;
}
//3、计算两链表长度的差值
int subValue = abs(lenA - lenB);//三目运算符也可以
//4、判断两个链表的长度关系:分三种情况,lenA>lenB,lenA<lenB,lenA=lenB
//假设默认lenA>lenB
struct ListNode* longList = headA;//这里还要用到头指针,所以前面不用头指针迭代。
struct ListNode* shortList = headB;
//矫正
if (lenB > lenA)
{
longList = headB;
shortList = headA;
}
//5、长的链表的指针先走subValue步
while (subValue)//subValue--,走subValue步
{
longList = longList->next;
subValue--;
}
//注意:遍历下标,一般用for循环。
//6、两个指针同时走
while (longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
return longList;//返回任意一个指针即可
}
思路3:求交点:长的链表先走(长度差)步,在同时走,第一个地址相同的就是交点。
计算A和B两个链表的长度,假设分别为lA、lB(A比B短),差值为k,
两个指针headA、headB,分别指向两个链表的头,让他们同时走,headA(短)每次走一步,headB(长)每次走k步或者让headB(长)先走k步,再同时走(方法2)。
当他们的地址相同时,即为交点的结点的地址。
注意: 前面是先判断尾节点是否相同,判断是否相交。再求相交节点。 下面是假设相交,求相交节点的,如果存在相交节点,则判断相交。
代码实现3:
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
//1、计算两个链表的长度
//定义两个变量存放头结点,防止迭代时头结点的值改变
struct ListNode* curA = headA;
int lA = 0;
while (curA != NULL)
{
lA++;
curA = curA->next;
}
struct ListNode* curB = headB;
int lB = 0;
while (curB != NULL)
{
lB++;
curB = curB->next;
}
//2、判断两个链表的长度关系:分三种情况,lA>lB,lA<lB,lA=lB
//假设默认lA>lB
struct ListNode* longList = headA;
struct ListNode* shortList = headB;
if (lB > lA)
{
longList = headB;
shortList = headA;
}
//3、计算两链表长度的差值
int subValue = abs(lA - lB);
//4、长的链表的指针先走subValue步
while (subValue)
{
longList = longList->next;
subValue--;
}
//5、两个指针同时走
while (longList)//有一个链表走到尾
{
if (longList == shortList)
{
return longList;
}
longList = longList->next;
shortList = shortList->next;
}
//来到这里,说明走到尾了也没有找到相交
return NULL;
}