题目:
输入两个链表,找出他们的第一个公共结点。
方法一:
在第一个链表上顺序遍历每个每个结点,每遍历到一个结点的时候,再第二个链表上顺序遍历每个结点。如果第二个链表上有一个结点和第一个链表上的结点一样,说明两个链表在这个结点上重合,于是就找到了他们的公共结点。
如果第一个链表的长度为O(m),第二个链表的长度为O(n),显然该方法的时间复杂度为O(mn)。
代码如下:
/*
输入两个链表,找出他们的第一个公共结点。
*/
#include<iostream>
#include"List.h"
using namespace std;
using namespace ListSpace5;
ListNode *FindFirstPulicNode(ListNode *root1, ListNode *root2)
{
if (root1 == nullptr || root2 == nullptr)
return nullptr;
while (root1 != nullptr)
{
int value = root1->element;
ListNode *tempRoot2 = root2;
while (tempRoot2 != nullptr)
{
if (tempRoot2->element == value && tempRoot2 == root1)
return tempRoot2;
tempRoot2 = tempRoot2->next;
}
root1 = root1->next;
}
return nullptr;
}
void test1()
{
ListNode *list1 = CreateListNode(1);
ListNode *list2 = CreateListNode(2);
ListNode *list3 = CreateListNode(3);
ListNode *list4 = CreateListNode(4);
ListNode *list5 = CreateListNode(5);
ListNode *list6 = CreateListNode(6);
ListNode *list7 = CreateListNode(7);
ConnectListNodes(list1, list2);
ConnectListNodes(list2, list3);
ConnectListNodes(list3, list6);
ConnectListNodes(list6, list7);
ConnectListNodes(list7, nullptr);
ConnectListNodes(list4, list5);
ConnectListNodes(list5, list6);
cout << "第一个链表:" << endl;
printList(list1);
cout << endl;
cout << "第二个链表:" << endl;
printList(list4);
cout << endl;
ListNode *result = FindFirstPulicNode(list1, list4);
if (result == nullptr)
cout << "两个链表无公共结点" << endl;
else
{
cout << "两个链表存在公共结点:";
printListNode(result);
}
cout << endl;
}
int main()
{
test1();
cout << endl;
system("pause");
return 0;
}
第一个链表:
1 2 3 6 7
第二个链表:
4 5 6 7
两个链表存在公共结点:The value of this node is 6
请按任意键继续. . .
方法二:
使用两个栈分别存储两个链表的各个结点,这样两个链表的尾结点就位于两个栈的栈顶,接下来比较两个栈顶的结点是否相同,如果相同,则把栈顶弹出接着比较下一个栈顶,直到找到一个相同的结点。
在上述思路中,需要借助两个辅助的栈,如果两个链表的长度分别为m和n,那么空间复杂度是O(m+n),时间复杂度是O(m+n)。
代码如下:
#include<iostream>
#include<stack>
#include"List.h"
using namespace std;
using namespace ListSpace5;
ListNode *FindFirstPulicNode2(ListNode *root1, ListNode *root2)
{
if (root1 == nullptr || root2 == nullptr)
return nullptr;
stack<ListNode *> stk1;
stack<ListNode *> stk2;
ListNode *temp1 = root1;
ListNode *temp2 = root2;
while (temp1 != nullptr)
{
stk1.push(temp1);
temp1 = temp1->next;
}
while (temp2 != nullptr)
{
stk2.push(temp2);
temp2 = temp2->next;
}
//如果最后一个结点都不同的话,直接返回nullptr
if (stk1.top() != stk2.top())
return nullptr;
ListNode *node = nullptr;
while (!stk1.empty() && !stk2.empty())
{
if (stk1.top() == stk2.top())
{
node = stk1.top();
stk1.pop();
stk2.pop();
}
else
return node;
}
return nullptr;
}
void test21()
{
ListNode *list1 = CreateListNode(1);
ListNode *list2 = CreateListNode(2);
ListNode *list3 = CreateListNode(3);
ListNode *list4 = CreateListNode(4);
ListNode *list5 = CreateListNode(5);
ListNode *list6 = CreateListNode(6);
ListNode *list7 = CreateListNode(7);
ConnectListNodes(list1, list2);
ConnectListNodes(list2, list3);
ConnectListNodes(list3, list6);
ConnectListNodes(list6, list7);
ConnectListNodes(list7, nullptr);
ConnectListNodes(list4, list5);
ConnectListNodes(list5, list6);
cout << "第一个链表:" << endl;
printList(list1);
cout << endl;
cout << "第二个链表:" << endl;
printList(list4);
cout << endl;
ListNode *result = FindFirstPulicNode2(list1, list4);
if (result == nullptr)
cout << "两个链表无公共结点" << endl;
else
{
cout << "两个链表存在公共结点:";
printListNode(result);
}
cout << endl;
}
int main()
{
test21();
cout << endl;
system("pause");
return 0;
}
第一个链表:
1 2 3 6 7
第二个链表:
4 5 6 7
两个链表存在公共结点:The value of this node is 6
请按任意键继续. . .
方法三
首先遍历两个链表得到他们的长度,这时候就知道哪个链表长以及长链表比锻炼表多出多少个结点。在第二次遍历的时候,先让较长的链表走上若干步,接着在同时在两个链表上遍历,找到第一个相同的结点就是他们的第一个公共结点。
时间复杂度为O(m+n),且不需要辅助空间。
代码如下:
#include<iostream>
#include"List.h"
using namespace std;
using namespace ListSpace5;
int GetListLength(ListNode *root)
{
int length = 0;
ListNode *temp = root;
while (temp != nullptr)
{
++length;
temp = temp->next;
}
return length;
}
ListNode *FindFirstPulicNode3(ListNode *root1, ListNode *root2)
{
if (root1 == nullptr || root2 == nullptr)
return nullptr;
int len1 = GetListLength(root1);
int len2 = GetListLength(root2);
int step = len1 - len2;
ListNode *nodeLong = root1;
ListNode *nodeShort = root2;
if (len2 > len1)
{
nodeLong = root2;
nodeShort = root1;
step = len2 - len1;
}
for (int i = 0; i < step; ++i)
nodeLong = nodeLong->next;
while (nodeLong != nullptr && nodeShort != nullptr)
{
if (nodeLong == nodeShort)
return nodeLong;
else
{
nodeLong = nodeLong->next;
nodeShort = nodeShort->next;
}
}
return nullptr;
}
void test31()
{
ListNode *list1 = CreateListNode(1);
ListNode *list2 = CreateListNode(2);
ListNode *list3 = CreateListNode(3);
ListNode *list4 = CreateListNode(4);
ListNode *list5 = CreateListNode(5);
ListNode *list6 = CreateListNode(8);
ListNode *list7 = CreateListNode(7);
ConnectListNodes(list1, list2);
ConnectListNodes(list2, list3);
ConnectListNodes(list3, list6);
ConnectListNodes(list6, list7);
ConnectListNodes(list7, nullptr);
ConnectListNodes(list4, list5);
ConnectListNodes(list5, list6);
cout << "第一个链表:" << endl;
printList(list1);
cout << endl;
cout << "第二个链表:" << endl;
printList(list4);
cout << endl;
ListNode *result = FindFirstPulicNode3(list1, list4);
if (result == nullptr)
cout << "两个链表无公共结点" << endl;
else
{
cout << "两个链表存在公共结点:";
printListNode(result);
}
cout << endl;
}
int main()
{
test31();
cout << endl;
system("pause");
return 0;
}
运行结果:
第一个链表:
1 2 3 8 7
第二个链表:
4 5 8 7
两个链表存在公共结点:The value of this node is 8
请按任意键继续. . .