1. 题目描述
输入两个链表,找出它们的第一个公共结点。
2. 题目分析
首先我们需要理解题目的含义,如果两个链表有公共结点,那么由于每个结点都只有一个指向,因此从公共结点开始,两个链表的后续结点都是重合的。两个链表呈横置的Y型。
然后开始考虑此题的解法:
(1)暴力解法
从第一个链表的头结点开始遍历,对于第一个链表的每一个结点,都遍历第二个链表进行比较,直到找到相同的结点。
下面是第一种想法的解法,本来以为没办法AC的,没想到直接AC了,这就很尴尬了。然鹅,不管怎样,面试官是不可能满意这种解法的,因此,我们必须要引入下面两种解法。
/*
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==NULL||pHead2==NULL)
return NULL;
ListNode *tmp1 = pHead1;
ListNode *tmp2 = pHead2;
while (tmp1 != NULL)
{
while (tmp2 != NULL)
{
if (tmp1 == tmp2)
{
return tmp1;
}
tmp2 = tmp2->next;
}
tmp2 = pHead2;
tmp1 = tmp1->next;
}
return NULL;
}
};
(2)先进后出---栈
正是因为相交的两个链表呈横置的Y型,而两个链表的长度又一定相同,因此,如果从头到尾依次比较各结点,并不能同时到达相交的结点;因此,我们想到从后往前比较结点,那么最后一对相同的结点,就是我们要找的结点。
为了实现这种方法,我们想到了栈的特性,因此我们需要建立两个栈,长度分别为m,和n,第一步先把两个链表中的数据全部放入栈中,第二步,再依次比较两个栈的栈顶元素,直到找到不同的那个结点为止。
实现代码如下:
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1==NULL||pHead2==NULL)
return NULL;
ListNode *result = NULL;
stack<ListNode*> stack1;
stack<ListNode*> stack2;
ListNode *p1 = pHead1;
ListNode *p2 = pHead2;
while (p1 != NULL)
{
stack1.push(p1);
p1 = p1->next;
}
while (p2 != NULL)
{
stack2.push(p2);
p2 = p2->next;
}
while (!stack1.empty() && !stack2.empty() && stack1.top() == stack2.top())
{
result = stack1.top();
stack1.pop();
stack2.pop();
}
return result;
}
};
这种解法的时间复杂度是O(m+n),空间复杂度也是m+n,通过牺牲空间换取时间效率,看似效率有很大的提高,但这种方法面试官仍然不会满意的(事儿多......),因此我们需要再考虑能否不牺牲空间,仍然可以获得较好的时间效率。
(3)求长度之差
在第二种方法中,我们之所以要用到栈,是因为两个链表的长度不一致,我们没有办法同时达到相交的结点。因此我们可以先求出两个链表的长度,算出两个链表的长度之差,然后较长的链表可以先前行delterx步,使得两个链表可以同时达到相交的结点;然后再依次比较两个链表,直到找到相同的结点为止。
代码实现如下:
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1==NULL||pHead2==NULL)
return NULL;
ListNode *tmp1 = pHead1;
ListNode *tmp2 = pHead2;
int length1 = 0;
int length2 = 0;
while(tmp1!=NULL)
{
length1++;
tmp1 = tmp1->next;
}
while(tmp2!=NULL)
{
length2++;
tmp2 = tmp2->next;
}
tmp1 = pHead1;
tmp2 = pHead2;
for(int i = 0; i < abs(length1-length2); i++)
{
tmp1 = tmp1->next;
}
while(tmp1!=NULL && tmp2!=NULL)
{
if(tmp1 == tmp2)
{
return tmp1;
}
tmp1 = tmp1->next;
tmp2 = tmp2->next;
}
return NULL;
}
};