题目描述:
输入两个链表,找出它们的第一个公共结点。
题目分析:
两个链表要有公共结点,就必须要有公共的尾部,从最后一个节点开始,最后一个不相等的节点就是第一个公共的节点。
方法一:使用栈来实现:将两个链表分别push进两个栈中,然后不断的pop,用一个FirCom来记录相等的节点,pop一个值,就更新一下FirCom,最后一次记录的FirCom值就是第一个公共的节点。
AC代码:
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
stack<ListNode*> s1;
stack<ListNode*> s2;
if(pHead1 == NULL || pHead2 == NULL)
return NULL;
while(pHead1)
{
s1.push(pHead1);
pHead1 = pHead1->next;
}
while(pHead2)
{
s2.push(pHead2);
pHead2 = pHead2->next;
}
ListNode* firCom = NULL;
while(!s1.empty() && !s2.empty())
{
ListNode* top1 = s1.top();
ListNode* top2 = s2.top();
s1.pop();
s2.pop();
if(top1 == top2)
firCom = top1;
}
return firCom;
}
};
方法二:需要先遍历两个链表,求出两个链表的长度,让长的链表先走长度差值步step,再同时走,第一个相等的节点就是第一个公共结点。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
int len1 = LengthOfList(pHead1);
int len2 = LengthOfList(pHead2);
if(len1 > len2)
pHead1 = WalkStep(pHead1,len1-len2);
else
pHead2 = WalkStep(pHead2,len2-len1);
while(pHead1 != NULL)
{
if(pHead1 == pHead2)
return pHead1;
pHead1 = pHead1->next;
pHead2 = pHead2->next;
}
return NULL;
}
int LengthOfList(ListNode* Head)
{
if(Head == NULL)
return 0;
int count = 0;
while(Head)
{
count++;
Head = Head->next;
}
return count;
}
ListNode* WalkStep(ListNode* Head, int step)
{
while(step--)
{
Head = Head->next;
}
return Head;
}
};
方法三:代码简洁,很巧妙的方法。p1,p2两个指针分别指向pHead1,pHead2,p1,p2一直往后走,当p1走到末尾的时候,让p1=pHead2,p1,p2再一直走,当p2走到末尾的时候,让p2=pHead1,此时p1,p2之间的相差的步数就是长度差,再一直走,走到第一个相等的节点就是所求。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
while(p1 != p2)
{
if(p1 != NULL)
p1 = p1->next;
if(p2 != NULL)
p2 = p2->next;
if(p1 != p2)
{
if(p1 == NULL)
p1 = pHead2;
if(p2 == NULL)
p2 = pHead1;
}
}
return p1;
}
};
方法四:使用map:map中存节点的指针和一个整型,用来标记节点。遍历一遍pHead1,在map中以ListNode*为索引值建立标记,第二次遍历pHead2,如果cur存在在map中说明是公共结点,第一次遍历到的公共结点,就是第一个公共结点。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
map<ListNode*,int> map;
ListNode* cur = pHead1;
while(cur)
{
map[cur] = 1;
cur = cur->next;
}
cur = pHead2;
while(cur){
if(map[cur])
return cur;
cur = cur->next;
}
return NULL;
}
};
(*^▽^*)