剑指offer36_两个链表的第一个公共结点_题解
两个链表的第一个公共结点
题目描述
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
分析
方案一:双指针法
思路:我们使用两个指针 p1,p2 分别指向两个链表 pHead1,pHead2 的头结点,然后同时分别逐结点遍历,当 p1 到达链表 pHead1 的末尾时,重新定位到链表 pHead2 的头结点;当 p2 到达链表 pHead2 的末尾时,重新定位到链表 pHead1 的头结点。这样,当它们相遇时,所指向的结点就是第一个公共结点。
理解:两个链表长度分别为L1+C、L2+C, C为公共部分的长度(包含末尾的NULL),按照楼主的做法: 第一个人走了L1+C步后,回到第二个人起点走L2步;第2个人走了L2+C步后,回到第一个人起点走L1步。 当两个人走的步数都为L1+L2+C时就两个指针就相遇了。如果没有公共结点就会在链表尾部NULL的位置相遇。
代码
/**
1.时间复杂度:O(M+N)
M+N代表两个链表的长度之和
2.空间复杂度:O(1)
只有指针p1和指针p2占用了额外空间
**/
class Solution
{
public:
ListNode *FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
{
ListNode *p1 = pHead1, *p2 = pHead2;
while (p1 != p2)
{
p1 = p1 ? p1->next : pHead2;
p2 = p2 ? p2->next : pHead1;
}
return p1;
}
};
方案二:链表等长法
先统计两个链表的长度,如果两个链表的长度不一样,就让链表长的先走,直到两个链表长度一样,两个链表再同时每次往后移一步,看节点是否一样,如果有相等的,说明这个相等的节点就是两链表的交点,否则如果走完了还没有找到相等的节点,说明他们没有交点,直接返回null即可
代码
/**
1.时间复杂度:O(M+N)
2.空间复杂度:O(1)
**/
class Solution
{
public:
ListNode *FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
{
ListNode *p1 = pHead1, *p2 = pHead2;
int l1 = 0, l2 = 0;
while (p1) //求链表1的长度
{
p1 = p1->next;
l1++;
}
while (p2) //求链表2的长度
{
p2 = p2->next;
l2++;
}
p1 = pHead1;
p2 = pHead2;
//让p1为最长链表的头,l1为其长度
if (l2 > l1)
{
swap(l1, l2);
swap(p1, p2);
}
//求长度差
int gap = l1 - l2;
//让p1和p2在同一起点上
while (gap--)
{
p1 = p1->next;
}
//遍历p1和p2,遇到相同则直接返回
while (p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
};