树的遍历(已知两种求第三种)

相信大家都知道树有三种遍历,前序遍历,中序遍历,后续遍历。我们平时会遇到一直其中两种遍历结果,让我们求第三种遍历。但并不是每种情况都可能的,有一个特殊情况就是已知前序遍历和后续遍历,我们并不能求出中序遍历,但我们可以求出中序遍历可能出现的情况。

已知前序遍历和中序遍历,求后序遍历

https://www.luogu.com.cn/problem/P1827  模板题链接

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
using ll = long long;
string a, b, c;//a为前序,b为中序,c为后序
//根据前序的顺序为根左右,我们可以知道,前序的首位一定是它的根
//继而我们可以通过find函数,找到该根再中序的位置,找到后,左边就是左子树,右边就是右子树,然后dfs
void solve(string a, string b) {
	if (a.empty())return;
	char root = a[0];
	int k = b.find(root);
	a.erase(a.begin());
	solve(a.substr(0, k), b.substr(0, k));
	solve(a.substr(k), b.substr(k + 1));//左闭右开,对与substr如果只有一个参数,那就一直截到尾
	c += root;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cin >> b >> a;
	solve(a, b);
	cout << c;
	return 0;
}

已知中序遍历和后序遍历,求前序遍历

https://www.luogu.com.cn/problem/P1030  模板题链接

代码具体实现与上面的很相似,可以先试着自己写一遍

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
using ll = long long;
string a, b, c;
void solve(string b, string c) {
	if (b.empty())return;//其实判断c也可以,没区别,始终一样长
	char root = c[c.size() - 1];//注意这里的处理
	int k = b.find(root);
	c.erase(c.size() - 1);
	a += root;//因为求的是前序,注意顺序
	solve(b.substr(0, k), c.substr(0, k));
	solve(b.substr(k + 1), c.substr(k));
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cin >> b >> c;
	solve(b, c);
	cout << a;
	return 0;
}

已知前序遍历和后续遍历,求中序遍历有几种情况

只知道前序遍历和后续遍历是无法求出中序遍历,只能求出中序遍历有几种情况。具体求法见代码。

https://www.luogu.com.cn/problem/P1229  题目链接

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
using ll = long long;
string a, c; ll ans;
//解出这道题的关键在与找到规律
//前序是根左右,后序是左右根,不难发现,左子树和右子树肯定是同时出现的
//但如果前序中出现AB而后序中出现BA明显调换了顺序,  
//先序遍历中A如果只有一个子树,A一定在B前面,后序遍历中B一定在A前,很容易想明白。
//如果只有一颗子树是左还是右呢?,就会使结果*2
//   AB    前序
//  BA     后序
//会出现上图情况
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cin >> a >> c;
	for (int i = 0; i < a.size(); i++) {
		for (int j = 1; j < c.size(); j++) {
			if (a[i] == c[j] && a[i + 1] == c[j - 1])
				ans++;
		}
	}
	cout << (1 << ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值