给出一颗二叉树的后序遍历和中序遍历,你能计算出两个结点的最近公共祖先吗?
输入格式:
第一行给出两个整数N(N<=10000)和M(M<=10000),分别代表二叉树的结点数和我们接下来的询问数。
第二行和第三行分别给出N个整数,每个整数用空格分开,分别代表二叉树的后序遍历和中序遍历。
接下来M行,每行给出两个整数,代表我们要询问的两个结点的编号a和b。
输出格式:
对于每个我们要求的询问:
1.如果a和b中有一个或两个不在树上,输出"ERROR"。
2.否则在一行中输出一个整数,表示a和b的最近公共祖先。
输入样例:
在这里给出一组输入。例如:
3 3
2 3 1
2 1 3
1 2
2 3
0 3
输出样例:
在这里给出相应的输出。例如:
1
1
ERROR
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
一道很有意思的二叉树递归题。我的肯定不是最优解。可以去社区看看其他博主的分享。
这里引用一下其他博主的博客图片做一下解释:(我的算法下标是从1开始到n结束)。
ACcode:
#include<iostream>
#include<queue>
using namespace std;
void find_father(int,int,int*,int*,int*,int*,int);
int main(){
int n, m,p,q;
int post[10000] = { 0 }, in[10000] = {0};
int index_in[10000] = { 0 }, index_post[10000] = {0};
//index数组记录p,q对应的值在in和post中出现的位置
// (这里起始位置从1开始,将index[x]=0位置认为是x存在于0位置,即不存在)
//在这种情况下默认构建树的时候不存在值为0的节点。
cin >> n >> m;
for (int i =1; i <=n; i++) cin >> post[i],index_post[post[i]]=i;
for (int i = 1; i <= n; i++) cin >> in[i],index_in[in[i]]=i;
for (int i = 1; i <= m; i++) {
cin >> p >> q;
find_father(p, q, index_in,index_post, post, in, index_in[post[n]]);
}
}
//index_in,index_post:表示值为x的节点在in和post中的位置。index[x]=0表示x不存在。
//root_index表示当前递归进程中所到根节点在in中的位置
void find_father(int p, int q, int* index_in,int* index_post, int* post, int* in, int root_index) {
if (!index_in[p] || !index_in[q]) {
cout << "ERROR" << endl;
return;
}//p或者q若不存在
if (index_in[p] == root_index || index_in[q] == root_index) {
cout << in[root_index] << endl;
return;
}//当p或者q有一个为两者的根节点
if (index_in[p] <root_index && index_in[q]< root_index) {
int post_lchild_index = root_index - 1;
find_father(p, q, index_in,index_post, post, in, index_in[post[post_lchild_index]]);
}//若p,q均在根节点左边,往根节点的左子树找father
else if(index_in[p] > root_index && index_in[q] > root_index) {
int post_rchild_index = index_post[in[root_index]];
find_father(p, q, index_in,index_post, post, in, index_in[post[post_rchild_index-1]]);
}//若p,q均在根节点的右边,往根节点的右子树找father
else {
cout << in[root_index] << endl;
return;
}//p,q在root的两侧,root即为公共祖先
}