原题链接:https://leetcode.cn/problems/intersection-of-two-linked-lists/description/
目录
1. 题目描述
2. 思路分析
3. 代码实现
1. 题目描述
2. 思路分析
看到这道题,很容易想到的方法就是暴力求解,就是将一个链表的每个结点的地址分别和另外一个链表的每个结点的地址进行比较,如果有相等的,就说明相交了。(注意这里不能比值,因为两个不同的结点值有可能一样)。但是这样的时间复杂度太高了,为O(N^2)。
这道题有一个很好的做法:
先计算出两个链表的长度,让长的链表先走相差的长度,然后两个链表同时走,直到遇到相同的结点,即为第一个公共结点。
我们定义了四个变量curA,curB,lenA,lenB。
我们用结构体指针curA遍历链表A,用结构体指针curB遍历链表B。
lenA表示链表A的长度,lenB表示链表B的长度。
用while循环通过遍历分别得到了链表A和B的长度。
我们判断尾结点是否相等,如果尾结点相等,说明两个链表一定相交!!!
(我们看下图,如果两个链表相交,那么从这个相交的结点(包括这个交点)之后的结点,在两个链表中都是相等的。所以尾结点相等,说明两个链表一定相交。)
如果两个链表不相交(curA!=curB),我们直接返回空指针NULL。
如果两个链表相交,我们先让长的链表走两个链表长度的差距步(gap)。因为不知道两个链表哪个长,所以我们使用了abs()函数,差距步gap就是abs(lenA-lenB)。
之后我们又引入了两个结构体指针longList和shortList分别指向长链表和短链表的头。这里用了if语句判断,先假设某个链表是长链表,如果不是,就让它等于短链表。
然后我们用一个while循环让长链表走差距步(while(gap--))。
然后让longList和shortList这两个结构体指针同时走,找交点,找到交点时结束循环。
最后返回longList即可。
3. 代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *curA=headA,*curB=headB;
int lenA=1,lenB=1;
//计算链表长度
while(curA->next)
{
curA=curA->next;
++lenA;
}
while(curB->next)
{
curB=curB->next;
++lenB;
}
//不相交
if(curA!=curB)
return NULL;
int gap=abs(lenA-lenB);
struct ListNode *longList=headA,*shortList=headB;
if(lenA<lenB)
{
longList=headB;
shortList=headA;
}
//长的先走差距步
while(gap--)
{
longList=longList->next;
}
//同时走找交点
while(longList!=shortList)
{
longList=longList->next;
shortList=shortList->next;
}
return longList;
}