刚刚做到一道乍眼一看很懵逼的题 先看题目:
给定两个单链表,编写算法找出两个链表的公共结点。
一开始以为公共结点是只要两个链表中有相同元素值的结点就是公共结点 但是在两个无序的链表中需要自己只能想到一个蛮力法
复杂度O(len1*len2)的算法 后来上度娘请教了公共结点。
公共结点:如果两个单向链表有公共的结点,也就是说两个链表从某一结点开始,
后面的结点都能对应相等,直到两个链表的链尾。
举个例子:
A 1 3 2 4 6
B 1 5 7 2 4 6
公共结点 2 4 6
也就是从第一个公共结点开始,之后它们所有结点都是重合的,不可能再出现分叉。
知道了这点 我们就可以写出一个复杂度O(len1+len2)的算法思想:
我们应该想到如果两个链表有公共结点 那么链尾的值一定相等 但由于这是单向链表 因此我们只能把长的那个链表的多出来的部分砍掉
从而就可以容易比较出第一个等值的结点
网上说的这是一道微软的面试题Orz 下面抛算法:
using namespace std;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode;
void CreatList(LNode *&L, int n)
{
LNode *p, *q;
L = (LNode *) malloc (sizeof(LNode));
L->next = NULL;
q = L;
for(int i = 0; i < n; i++){
p = (LNode *) malloc (sizeof(LNode));
p->next = NULL;
cin>>p->data;
q->next = p;
q = p;
}
}
void ListLength(LNode *L, int &len)
{
len = 0;
LNode *p;
p = L->next;
while(p){
++len;
p = p->next;
}
}
LNode *SearchCommon(LNode *L1, LNode *L2)
{
int len1, len2, dist;
ListLength(L1, len1);
ListLength(L2, len2);
LNode *ShortList, *LongList;
if(len1 >= len2){
LongList = L1->next;
ShortList = L2->next;
dist = len1 - len2;
}
else{
LongList = L2->next;
ShortList = L1->next;
dist = len2 - len1;
}
while(dist--)
LongList = LongList->next;
while(LongList && ShortList && LongList->data != ShortList->data){
LongList = LongList->next;
ShortList = ShortList->next;
}
return LongList;
}
void Print(LNode *L)
{
LNode *p;
p = L->next;
while(p){
cout<<p->data<<' ';
p = p->next;
}
cout<<endl;
}
void Print2(LNode *L) //这里是没有头结点开始遍历
{
LNode *p;
p = L;
if(!p){
cout<<"NULL!"<<endl;
return;
}
while(p){
cout<<p->data<<' ';
p = p->next;
}
cout<<endl;
}
int main()
{
int n, m;
LNode *L1, *L2;
cin>>n>>m;
CreatList(L1, n);
CreatList(L2, m);
Print(L1);
Print(L2);
LNode *p = SearchCommon(L1, L2);
Print2(p);
return 0;
}