题目描述
160.相交链表
编写一个程序,找到两个单链表相交的起始节点。
示例1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
注:此处相交是指结点的地址相等,而不是val相等
注:
如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
题解
先分别用两个指针求出两个链表的长度,再看尾指针的地址是否相同,相同则证明具有相交结点,然后在求出他们的差距步,然后再让长的链表先走差距步,之后两个链表的指针再同时走,直到遇到相等为止,则证明找到了相交结点
初始情况:
①将tailA和tailB两个指针向后走一直遍历到尾(因为要比较尾指针的地址是否相等,所以不能直接走到NULL),求出两个链表的长度,并判断 tailA 和 tailB 是否相等,不等则直接返回NULL
②首先重置 tailA 和 tailB,使他们重新指向头结点,再求出差距步diff = lenB - lenA,并让长链表B先走差距步
③ tailA 和 tailB 同时往后走,直到两指针相等为止。(再前面已经验证过是否有相等结点)
题解代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA == NULL || headB == NULL)
{
return NULL;
}
int lenA = 0,lenB = 0;
struct ListNode *tailA = headA,*tailB = headB;
//求出长度
while(tailA || tailB)
{
if(tailA != NULL)
{
lenA++;
tailA = tailA->next;
}
if(tailB != NULL)
{
lenB++;
tailB = tailB->next;
}
}
//查看尾指针,看地址(不是值)是否相等,相等则说明有相交结点
if(tailA != tailB)
{
return NULL;
}
//让尾指针重新指向头结点
tailA = headA;
tailB = headB;
int diff = (lenA < lenB) ? lenB-lenA : lenA-lenB;
//让长的链表先走差距步
while(diff--)
{
if(lenA < lenB)
{ //B链表长
tailB = tailB->next;
}else
{
tailA =tailA->next;
}
}
//前面已经证明过,这两个链表是有相交结点的
//让两个同时再走,当相等时则跳出循环
while(tailA != tailB)
{
tailA = tailA->next;
tailB = tailB->next;
}
return tailA;
}