题目:输入两个链表,找到它们的第一个公共结点。
思路一:蛮力法 在第一个链表上顺序遍历每一个结点,每遍历一个节点在第二个链表顺序遍历每一个结点,如果第二个链表上有一个结点和第一个链表上一样,说明两个链表在这个结点上重合,于是就找到它们的公共结点。len1 = m,len2 = n,时间复杂度为O(mn)。
思路二:栈 分别把两个链表的结点放入两个栈里,这样两个链表的尾结点就位于两个栈的栈顶,接下来就比较两个栈顶结点是否相同,如果相同则弹出比较下一个,直到找到最后一个相同的结点。时间复杂度O(m+n)。
思路三:比较两个链表的长度,让长的先走多出的结点步,然后两个指针一起走同时比较,如果相等便是第一个公共结点。时间复杂度O(m+n)。不需要借助栈,提高了空间效率。
代码如下:
template<class T>
struct ListNode
{
T _value;
ListNode<T>* _next;
ListNode(const T& value)
:_value(value),_next(NULL)
{}
};
template<class T>
class List
{
public:
List()
:_head(NULL)
{}
bool PushBack();
ListNode<T>* FindCommNode1(List<T> l)//寻找两个链表中第一个公共节点—蛮力法
{
ListNode<T>* head1 = _head;
ListNode<T>* head2 = l.Head();
int len1 = Length();
int len2 = l.Length();
for(int i=0;i<len1;++i)
{
for(int j=0;j<len2;++j)
{
if(head1 == head2)
return head1;
else
{
head2 = head2->_next;
}
}
head1 = head1->_next;
head2 = l.Head();
}
cout<<"没有公共节点"<<endl;
return NULL;
}
ListNode<T>* FindCommNode2(List<T> l)//寻找两个链表中第一个公共节点—借助栈
{
stack<ListNode<T>*> s1;
stack<ListNode<T>*> s2;
ListNode<T>* head1 = _head;
ListNode<T>* head2 = l.Head();
while(head1!=NULL)
{
s1.push(head1);
head1 = head1->_next;
}
while(head2!=NULL)
{
s2.push(head2);
head2 = head2->_next;
}
ListNode<T>* tmp = NULL;
while(!s1.empty()&&!s2.empty())
{
if(s1.top() == s2.top())
{
tmp = s1.top();
s1.pop();
s2.pop();
}
else
{
if(tmp)
return tmp;
else
return NULL;
}
}
}
ListNode<T>* FindCommNode3(List<T> l)//Y 寻找两个链表中第一个公共节点—求长度,长链表先走多余的长度,然后一起走比较直到节点相等停止
{
ListNode<T>* head1 = _head;
ListNode<T>* head2 = l.Head();
int len1 = Length();
int len2 = l.Length();
if(len1 > len2)
{
int sub = len1 - len2;
while(sub--)
{
head1 = head1->_next;
}
}
if(len1 < len2)
{
int sub = len2 - len1;
while(sub--)
{
head2 = head2->_next;
}
}
while(head1!=NULL && head2!=NULL)
{
if(head1 == head2)
return head1;
else
{
head1 = head1->_next;
head2 = head2->_next;
}
}
}
private:
ListNode<T>* _head;
};