题目:
输入两个链表,输出两个链表的第一个公共结点。
分析:
由于单链表的结点,每个结点只有一个next指针,所以 两个链表的连接形式像是一个Y型。
经分析:若两个链表存在公共结点,则公共结点位于链表尾部。若我们从链表尾部开始往前比较,最后一个相同的结点就是我们要找的结点。可以在单链表中,只能从头结点开始按顺序遍历,最后才能到达尾结点。类似于后进先出。联想到可以用栈来解决该问题。
分别把两个链表的结点放到到两个栈里,这样两个链表的尾结点就位于两个栈的栈顶,接下来比较两个栈顶的结点是否相同。若下行同,则弹出栈顶,比较下一个栈顶,知道找到最后一个相同的结点。
该思路需要用两个辅助栈。若链表长度分别为m和n,那么空间复杂度为O(m+n),时间复杂度也是O(m+n)。
之所以需要用到栈,是因为我们想同时遍历到连个栈的尾结点。当两个链表的长度不相同时,如果我们从头开始遍历到达尾结点的时间就不一致。可以首先遍历两个链表得到他们长度,在第二次遍历的时候,在较长的链表上先走若干不,接着再同时在两个链表上遍历,找到的第一个相同的结点就是他们的第一个公共结点。
//求两个链表的第一个公共结点;
struct ListNode
{
int value;
ListNode *next;
ListNode(const int &value):value(value),next(NULL)
{
}
};
unsigned int GetLength(ListNode *Head)
{
if(Head==NULL)
retutn 0;
unsigned int Length=0;
ListNode *pNode=Head;
while(pNode->next!=NULL)
{
length++;
pNode=pNode->next;
}
return length;
}
ListNode *FirstCommonNode(ListNode *Head1,ListNode *Head2)
{
if(Head1==NULL||Head2==NULL)
return NULL;
unsigned int length1=GetLength(Head1);
unsigned int length2=GetLength(Head2);
int lengthdif=length1-length2;
ListNode *pLongNode=Head1;
ListNode *pShortNode=Head2;
if(length1<length2)
{
pLongNode=Head2;
pLongNode=Head1;
lengthdif=length2-length1;
}
for(int i=0;i<lengthdif;i++)
{
pLongNode=pLongNode->next;
}
while(pLongNode!=NULL&&pShortNode!=NULL&&pLongNode!=pShortNode)
{
pLongNode=pLongNode->next;
pShortNode=pShortNode->next;
}
ListNode *FirstCommonNode=pLongNode;
return FirstCommonNode;
}