出题人 陈越
单位 浙江大学
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
其左子树中所有结点的键值小于该结点的键值;
其右子树中所有结点的键值大于等于该结点的键值;
其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
输入格式
输入的第一行给出正整数 N(≤1000)。随后一行给出 N 个整数键值,其间以空格分隔。
输出格式
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出 YES ,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出 NO。
输入样例
7
8 6 5 7 10 8 11
输出样例
YES
5 7 6 8 11 10 8
输入样例2
7
8 10 11 8 6 7 5
输入样例2
YES
11 8 10 7 5 6 8
输入样例3
7
8 6 8 5 10 9 11
输入样例3
NO
思路
前序遍历:根 左 右
中序遍历:左 根 右
后序遍历:左 右 根
这个二叉搜索树左子树比根小,右子树比根大,因此我们直接dfs得到后序遍历
具体做法:找到当前树前序遍历的左右边界l和r,通过dfs函数执行,ll为第一个比根大的结点位置,即右子树起点位置,rr为第一个比根小的结点的位置,即左子树终点位置,ll和rr位置差为1,查找得到ll和rr的数据。之后就是递归,dfs传左子树位置,dfs传右子树位置,最后把当前根放入vector容器。当全部操作执行完毕之后,得到的vector容器存储的数据即为后序遍历的数据。
有帮助请点个赞
下面上代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int pre[1010];
vector<int> v;
int flag = 1;
void dfs(int l, int r)
{
if(l > r)
return;
int ll = l+1, rr = r;
if(flag){
while(ll <= r && pre[ll] < pre[l])
ll++;
while(rr > l && pre[rr] >= pre[l])
rr--;
}else{
while(ll <= r && pre[ll] >= pre[l])
ll++;
while(rr > l && pre[rr] < pre[l])
rr--;
}
if(ll-rr != 1)
return;
dfs(l+1, rr);
dfs(ll, r);
v.push_back(pre[l]);
}
int main()
{
int n;
cin>>n;
for(int i = 0; i < n; i++)
cin>>pre[i];
dfs(0, n-1);
if(v.size() != n){
flag = 0;
v.clear();
dfs(0, n-1);
}
if(v.size() != n)
cout<<"NO"<<endl;
else{
cout<<"YES"<<endl;
cout<<v[0];
for(int i = 1; i < v.size(); i++)
cout<<' '<<v[i];
cout<<endl;
}
}