题目:输入两个链表,找出它们的第一个公共结点。链表结点定义如下:
struct ListNode
{
int m_nkey;
ListNode* m_pNext;
};
分析:如果两个单链表有公共结点,那么公共结点之后的结点全都是是两个链表的公共结点。我们可以从后往前遍历两个单链表,直到遍历到的结点不同为止。
一、使用栈可以实现单链表的反向遍历。
class Solution
{
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2 )
{
stack<ListNode*> list1;
stack<ListNode*> list2;
ListNode* pList = NULL;
while ( pHead1 != NULL )
{
list1.push( pHead1 );
pHead1 = pHead1->m_pNext;
}
while ( pHead2 != NULL )
{
list2.push( pHead2 );
pHead2 = pHead2->m_pNext;
}
while ( list1.empty() || list2.empty() )
{
if ( list1.top() != list2.top() )
{
return pList;
}
pList = list1.top();
list1.pop();
}
return pList;
}
};
二、先将两个链表遍历一遍,得到两个链表的长度,然后先在较长链表走几步,然后同时前进,这种方法的时间复杂度也是O(m+n),但是不需要额外的辅助空间。
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if ( pHead1 == NULL || pHead2 == NULL )
return NULL;
int lenList1, lenList2;
ListNode* ppHead1 = pHead1;
ListNode* ppHead2 = pHead2;
while ( pHead1 != NULL )
{
lenList1++;
pHead1 = pHead1->next;
}
while ( pHead2 != NULL )
{
lenList2++;
pHead2 = pHead2->next;
}
pHead2 = ppHead2;
pHead1 = ppHead1;
int forward = lenList1 - lenList2;
if ( forward < 0 )
{
forward = -forward;
while ( forward-- )
{
pHead2 = pHead2->next;
}
}
else
{
while ( forward-- )
{
pHead1 = pHead1->next;
}
}
while ( pHead1 != pHead2 && pHead1 != NULL && pHead2 != NULL )
{
pHead1 = pHead1->next;
pHead2 = pHead2->next;
}
return pHead1;
}
};