要求:给定先序和中序,确定一棵树,然后给定两个key值,在树中查找离两个结点最小路径的祖先结点,并按要求输出。
方法:由先序和中序先建立树,并存每个节点的父亲结点和深度。树不一定需要链表存储,可以用数组。
考场上和平时写代码还是不一样。
代码:
#include<bits/stdc++.h>
using namespace std;
int pre[10000],in[10000];
map<int,pair<int,int> >no; //因为key的范围为int,用数组存会内存超限
map<int,bool>flag;
void totree(int inL,int inR,int preL,int pa,int le) //建树和存父亲结点和深度
{
if(inL>inR)return ;
int i=inL;
no[pre[preL]]=make_pair(le,pa);
while(in[i]!=pre[preL])++i;
totree(inL,i-1,preL+1,pre[preL],le+1);
totree(i+1,inR,preL+i-inL+1,pre[preL],le+1);
}
int main()
{
//freopen("test.txt","r",stdin);
int N,M,i;
scanf("%d %d",&M,&N);
for(i=0;i<N;++i)scanf("%d",&in[i]);
for(i=0;i<N;++i)scanf("%d",&pre[i]),flag[pre[i]]=1;
totree(0,N-1,0,-1,0);
while(M--){
int a,b;
scanf("%d %d",&a,&b);
if(!flag[a]&&!flag[b])printf("ERROR: %d and %d are not found.\n",a,b);
else if(!flag[a]||!flag[b])printf("ERROR: %d is not found.\n",flag[a]?b:a);
else{
if(a==b)printf("%d is an ancestor of %d.\n",a,b); //相等时是按这种方式,不是另外一种
else if(no[a].second==b||no[b].second==a)printf("%d is an ancestor of %d.\n",no[a].second==b?b:a,no[a].second==b?a:b);
else{
int x=a,y=b;
//printf("LCA of %d and %d is ",a,b);
if(no[a].first<no[b].first){ //其中一个是另一个的祖先结点
while(no[a].first<no[b].first)b=no[b].second;
}else{
while(no[a].first>no[b].first)a=no[a].second;
}
if(a==b)printf("%d is an ancestor of %d.\n",a==x?a:b,a==x?y:x);
else{ //达到同一层,两个不等
while(a!=b)a=no[a].second,b=no[b].second;
printf("LCA of %d and %d is %d.\n",x,y,a);
}
}
}
}
return 0;
}