首先明确公共节点的定义,即两个链表从某一节点开始,他们的next指针都指向同一个节点。
方法1,暴力穷举
看到这题的第一个思路,就是直接遍历,类似双层for循环,依次比较链表1和链表2每个节点,看有没有公共节点节点。思路比较简单,但时间复杂度高,为Olog(n^2)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(!pHead1 || !pHead2) return nullptr;
ListNode * p1= pHead1;
ListNode * p2= pHead2;
while(p1)
{
while(p2)
{
if(p1 == p2)
{
return p2;
}
else
{
p2=p2->next;
}
}
p2 = pHead2;
p1=p1->next;
}
return nullptr;
}
};
方法2,栈方法
如果两个链表有公共节点,那么一定是一个型,即从链表最后,到第一个公共节点为止,其间所有节点都是一样的。因此可以利用栈先入后出特性,把两个链表存入栈中,再pop出来,从后向前遍历,直到两个栈的栈顶元素不相等,则说明第一个公共节点在该位置的后面一个。但这种方法空间复杂度比较高
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(!pHead1 || !pHead2) return nullptr;
stack<ListNode*> s1;
stack<ListNode*> s2;
ListNode * p1 = pHead1;
ListNode * p2 = pHead2;
while(p1)
{
s1.push(p1);
p1 = p1->next;
}
while(p2)
{
s2.push(p2);
p2 = p2->next;
}
int temp = 0;
int size_1 = s1.size();
while(!s1.empty()&&!s2.empty())
{
if(s1.top()!=s2.top())
break;
else
{ s1.pop();
s2.pop();
temp++;
}
}
temp = size_1-temp;
ListNode *res = pHead1;
while(temp--)
{
res = res->next;
}
return res;
}
};
方法3,双指针
分析两个含有公共节点链表的结构,易知,
如果令两个链表长度相等,那么定义两个指针p1和p2,分别指向链表1和链表2头节点,两个指针同时开始向链表尾部移动,直到出现第一个相同的节点,就为公共节点。
如果两个链表长度不等,我们可以求出两个链表的长度差为s,然后令长链表先走s步,那么长链表剩下的节点数就和短链表的一样了,就可以同上了。
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(!pHead1||!pHead2) return nullptr;
ListNode *p1 = pHead1;
ListNode *p2 = pHead2;
int count1 = 0;
int count2 = 0;
int sub = 0;
while(p1){
p1=p1->next;
count1++;
}
while(p2){
p2=p2->next;
count2++;
} //以上为求长度
if(count1 > count2)
{
sub = count1-count2;
while(sub--)
{
pHead1=pHead1->next;
}
}
else
{
sub = count2-count1;
while(sub--)
{
pHead2=pHead2->next;
}
}
//以上代码让长链表先走sub步
while(pHead1!=pHead2)
{
pHead1=pHead1->next;
pHead2=pHead2->next;
}//以上为找出第一个相同节点
return pHead1;
}
};
方法4 双指针相遇
原理还没搞清楚,先放上链接记录一下
图解 双指针法,浪漫相遇
方法5 使用stl map
思路:将第一个链表的元素都存入map中,然后利用第二个链表作为key,在map中查找是否有相同元素,有则返回该节点
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(!pHead1 || !pHead2) return nullptr;
map<ListNode*,int> m;
while(pHead1)
{
m[pHead1] = pHead1->val;
pHead1 = pHead1->next;
}
while(pHead2)
{
if(m.find(pHead2)!= m.end())
return pHead2;
else
pHead2 = pHead2->next;
}
return nullptr;
}
};