@TOC
1. 题目
题目链接:找出两条相交链表的公共节点
2. 思路
最朴素的解法就是,把A链表中每个节点,与B链表中的所有节点比较,如果有地址相同的节点,就相交,第一个地址相同的即为交点,但也很暴力,时间复杂度$O(N^2)$
要求优化至$O(N)$?
:black_heart: 1. 判断两个链表是否相交
经过观察发现,相交链表的尾巴都是一样的。那我就比较尾节点好了,尾节点相同即相交,尾节点不同即不相交。
:black_heart: 2. 找交点
我们可以保证进链表前长度相同。求出链表长度$O(N)$,长的先走差距步,再一起走走,即可找到交点。
此题思路有了之后,代码实现是简单的,小注意点附在最后。
3. 题解及小注意点
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA == NULL || headB == NULL)
return NULL;
// 1.判断是否相交
struct ListNode * tailA = headA;
int lenA = 0;
struct ListNode * tailB = headB;
int lenB = 0;
//找尾
while(tailA->next)
{
tailA = tailA->next;
lenA++;
}
while(tailB->next)
{
tailB = tailB->next;
lenB++;
}
if(tailA != tailB)
return NULL;
// 2.找交点
// 假设法:假设A更长
struct ListNode * longList = headA;
struct ListNode * shortList = headB;
int gap = lenA - lenB;
if(lenA < lenB)
{
longList = headB;
shortList = headA;
gap = lenB - lenA;
}
while(gap--)
{
longList = longList->next;
}
while(shortList != longList)
{
longList = longList->next;
shortList = shortList->next;
}
return shortList;
}
小注意点
- [ ] 经典的假设法,否则我们不得不把相同的逻辑写两遍,like this ——
//找交点
if(lenA > lenB)
{
//A先走几步
tailA = headA;
while((lenA-lenB)--)
{
tailA = tailA->next;
}
}
else
{
tailB = headB;
//B先走几步
while((lenB-lenA)--)
{
tailB = tailB->next;
}
}
持续更新题解@边通书