PAT 甲级 1151 LCA in a Binary Tree (30 分)
太惭愧了,这题暴力解的,玩不来各个大佬的lca算法。
思路:
1.将中根先根序列存储,然后用递归分治分别求出每个key的父结点,同时记录结点层次;
2.用全局变量存储中根先根序列,然后以下标范围来限定子树范围,我之前在每次递归时又定义两个vector来复制树的一个区间,以起到遍历子树的效果,结果后三个内存超了;
3.对于每两个要检测的key,若不在树里,按要求输出;若在树里,则层次低的那个结点沿父结点往上爬,爬到和层次高的那个结点同一层次,然后它们同时往上爬,直到它们的值相等,那个值就是他们的最近共同祖先结点;最后按找到的那个值是不是它们中的一个按要求进行输出;
代码:
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
unordered_map<int,pair<int,int>> vec;
unordered_map<int,int> loca;
vector<int> inOr,preOr;
void findFather(pair<int,int> in,pair<int,int> pre,int level)
{
int root=loca[preOr[pre.first]];
if(root!=in.first)
{
vec[preOr[pre.first+1]]=make_pair(preOr[pre.first],level);
indFather(make_pair(in.first,root-1),make_pair(pre.first+1,root-in.first+pre.first),level+1);
}
if(root!=in.second)
{
vec[preOr[root-in.first+pre.first+1]]=make_pair(preOr[pre.first],level);
findFather(make_pair(root+1,in.second),make_pair(root-in.first+pre.first+1,pre.second),level+1);
}
}
int main()
{
int m,n,u,v;
scanf("%d%d",&m,&n);
inOr.resize(n); preOr.resize(n);
for(int i=0;i<n;i++)
{
scanf("%d",&inOr[i]);
loca[inOr[i]]=i
}
for(int i=0;i<n;i++) scanf("%d",&preOr[i]);
vec[preOr[0]]=make_pair(preOr[0],0);
findFather(make_pair(0,n-1),make_pair(0,n-1),1);
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
if((vec[u].first==0||vec[v].first==0)&&(vec[u].first!=0||vec[v].first!=0))
printf("ERROR: %d is not found.\n",vec[u].first==0?u:v);
else if(vec[u].first==0&&vec[v].first==0)
printf("ERROR: %d and %d are not found.\n",u,v);
else
{
int fau=u,fav=v;
while(vec[fau].second!=vec[fav].second)
vec[fau].second>vec[fav].second?fau=vec[fau].first:fav=vec[fav].first;
while(fau!=fav)
{
fau=vec[fau].first;
fav=vec[fav].first;
}
if(fau==u||fav==v)
printf("%d is an ancestor of %d.\n",fau==u?u:v,fau==u?v:u);
else
printf("LCA of %d and %d is %d.\n",u,v,fau);
}
}
return 0;
}