PTA 有趣的最近公共祖先问题 分数 15作者 章立晨 单位 浙大城市学院

给出一颗二叉树的后序遍历和中序遍历,你能计算出两个结点的最近公共祖先吗?

输入格式:

第一行给出两个整数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即为公共祖先
	
}

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值