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

本文介绍了一道关于利用后序遍历和中序遍历线索解决二叉树中查询两个节点最近公共祖先的问题,通过递归方法寻找答案,适用于IT技术中的数据结构和算法题型。

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

输入格式:

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

双端队列(Deque)是一种允许在两端进行插入和删除操作的队列。使用数组实现双端队列时,需要考虑数组的大小、队头和队尾的位置,以及如何处理队列满和队列空的情况。 ### 解题思路 1. **初始化**:创建一个固定大小的数组来存储队列元素,同时记录队头(`front`)和队尾(`rear`)的位置,初始时队列为空。 2. **插入操作**: - **队头插入**:将元素插入到队头位置,同时更新队头指针。 - **队尾插入**:将元素插入到队尾位置,同时更新队尾指针。 3. **删除操作**: - **队头删除**:移除队头元素,同时更新队头指针。 - **队尾删除**:移除队尾元素,同时更新队尾指针。 4. **边界条件**:在进行插入和删除操作时,需要检查队列是否已满或为空。 ### 代码示例 ```python class Deque: def __init__(self, size): self.size = size self.queue = [None] * size self.front = 0 self.rear = 0 self.count = 0 def is_full(self): return self.count == self.size def is_empty(self): return self.count == 0 def insert_front(self, item): if self.is_full(): print("Deque is full") return self.front = (self.front - 1) % self.size self.queue[self.front] = item self.count += 1 def insert_rear(self, item): if self.is_full(): print("Deque is full") return self.queue[self.rear] = item self.rear = (self.rear + 1) % self.size self.count += 1 def delete_front(self): if self.is_empty(): print("Deque is empty") return None item = self.queue[self.front] self.front = (self.front + 1) % self.size self.count -= 1 return item def delete_rear(self): if self.is_empty(): print("Deque is empty") return None self.rear = (self.rear - 1) % self.size item = self.queue[self.rear] self.count -= 1 return item def display(self): if self.is_empty(): print("Deque is empty") return index = self.front for _ in range(self.count): print(self.queue[index], end=" ") index = (index + 1) % self.size print() # 示例使用 deque = Deque(5) deque.insert_front(1) deque.insert_rear(2) deque.insert_front(3) deque.display() print(deque.delete_rear()) deque.display() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值