给定某个二叉树的中序遍历和前序遍历,求给定值对的最深共同父节点。
约等于1143 Lowest Common Ancestor,还是可以不建树(真的不想写树),区别在于1143给的是BST的前序遍历,本题只说了二叉树,因此就不能通过值的大小来判断是否在某节点的同一边。但是可以把中序遍历的顺序作为判断的标准,按中序给节点做上标记,判断时根据标记判断,之后的处理方式就和BST一样了。如果值a在中序遍历序列中的下标小于值b在中序遍历中的下标,那就可以看作a的标记值小于b的标记值。同样的根据前序遍历序列搜索节点,第一个满足节点的标记值在两所求值对应的标记值中间的节点就是所求的LCA。
输出的时候记得把标记值转化为原值。
#include <stdio.h>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int m,n;
map<int,int> val_to_pos;
int pre[10010],ino[10010];
void findAnc(int idx1,int idx2){
for(int i=0;i<n;i++){
int curridx=val_to_pos[pre[i]];
if((curridx>idx1 && curridx>idx2)||(curridx<idx1 && curridx<idx2))continue;
else if(idx1==curridx){
printf("%d is an ancestor of %d.\n",ino[idx1],ino[idx2]);
return;
}else if(idx2==curridx){
printf("%d is an ancestor of %d.\n",ino[idx2],ino[idx1]);
return;
}else if((idx1>curridx && idx2<curridx) || (idx1<curridx && idx2>curridx)){
printf("LCA of %d and %d is %d.\n",ino[idx1],ino[idx2],pre[i]);
return;
}
}
}
int main(){
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++){
scanf("%d",&ino[i]);
val_to_pos[ino[i]]=i;
}
for(int i=0;i<n;i++){
scanf("%d",&pre[i]);
}
for(int i=0;i<m;i++){
int key1,key2;
scanf("%d %d",&key1,&key2);
auto idx1=val_to_pos.find(key1);
auto idx2=val_to_pos.find(key2);
if(idx1==val_to_pos.end() && idx2==val_to_pos.end())printf("ERROR: %d and %d are not found.\n",key1,key2);
else if(idx2==val_to_pos.end())printf("ERROR: %d is not found.\n",key2);
else if(idx1==val_to_pos.end())printf("ERROR: %d is not found.\n",key1);
else{
findAnc(val_to_pos[key1],val_to_pos[key2]);
}
}
}