【题目描述】
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
题目及图片来源(力扣):相交链表
注:
题目数据保证整个链式结构中不存在环。
函数返回结果后,链表必须保持其原始结构 。
【基本思路】
先看比较特殊的情况,两个链表相交且长度相等(比如示例1的图去掉B左边的第一个节点)。这时只要双指针同时从各自的链表头开始向后走,等到两指针相等时便是相交的起始节点。
再看比较一般的情况,两个链表相交但长度不等(如示例1图)。这时我们想:如果能把长度差消除掉,不就回归上面的特殊情况了吗?那么有办法消除长度差吗?答案是有的:分别计算两个单链表的长度,然后取其差值,让长链表的节点指针从头开始先向后走差值个节点,然后和短链表的节点指针(它从短链表的头开始走)同时向后走,等到两指针相等时便是相交的起始节点。
那么如果两个链表不相交呢?这种情况如何处理?其实步骤跟上面的情况一样,只是最后的“相交节点”是 null 罢了(可以认为 null 是特殊的“相交节点”)。
【代码实现】
typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
//分别对两个单链表计算长度
int lenA = 0, lenB = 0;
ListNode* curA = headA, *curB = headB;
while(curA)
{
++lenA;
curA = curA->next;
}
while(curB)
{
++lenB;
curB = curB->next;
}
//两个单链表长度差
int gap = abs(lenA - lenB);
//先假设链表A更长
ListNode* longList = headA;
ListNode* shortList = headB;
if(lenA < lenB) // 如果链表B更长,就换过来
{
longList = headB;
shortList = headA;
}
//消除长度差
while(gap--)
{
longList = longList->next;
}
//双指针同时向后走
while(longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
//如果两者相等,则返回相交的起始节点(如果链表不相交,则返回空指针)
return longList;
}
复杂度分析:
时间复杂度:O(M + N),其中 M 和 N 分别为两链表的长度。
空间复杂度:O(1)。
别人想出了另一种解法,相对来说没那么好想,不过其代码很简洁。
别人的另一种解法(含清晰图解)
本专栏
有关链表的题目
其它专栏
有关数组的题目