题目描述
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
其左子树中所有结点的键值小于该结点的键值;
其右子树中所有结点的键值大于等于该结点的键值;
其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
输入
输入的第一行给出正整数N(<=1000)。随后一行给出N个整数键值,其间以空格分隔。
输出
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出“YES”,然后在下一行输出该树后序遍历的结果。数字间有1个空格,一行的首尾不得有多余空格。若答案是否,则输出“NO”。
样例输入1
7
8 6 5 7 10 8 11
样例输出1
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
思路
分原树和镜像树两种方式考虑
代码
#include <bits/stdc++.h>
using namespace std;
struct Node{
int val;
Node *lson, *rson;
};
int a[1010];
vector<int> v;
bool test(bool ori, int l, int r){//ori为true表示原树,false为镜像树
if(l >= r){//递归出口
return true;
}
int i, j;
for(i=l+1; i<=r; i++){
if(ori){
if(a[l] <= a[i]){
break;
}
}else {
if(a[l] > a[i]){
break;
}
}
}
bool flag = true;
for(j=i;j<=r; j++){
if(ori){
if(a[j] < a[l]){
flag = false;
break;
}
}else {
if(a[j] >= a[l]){
flag = false;
break;
}
}
}
if(flag){
return test(ori, l+1, i-1) && test(ori, i, r);
}else{
return false;
}
}
Node* create(bool ori, int l, int r){
if(l > r){
return NULL;
}
int i;
if(ori){
for(i=l+1; i<=r; i++){
if(a[l] <= a[i]){
break;
}
}
}else {
for(i=l+1; i<=r; i++){
if(a[l] > a[i]){
break;
}
}
}
//建立根节点
Node *p = (Node*)malloc(sizeof(Node));
p->val = a[l];
p->lson = create(ori, l+1, i-1);//左子树
p->rson = create(ori, i, r); //右子树
return p;
}
void postTraverse(Node *p){
if(p){
postTraverse(p->lson);
postTraverse(p->rson);
v.push_back(p->val);
}
}
int main(){
int n;
cin>>n;
for(int i=0; i<n; i++){
cin>>a[i];
}
Node* root;
bool flag = false;
if(test(true, 0, n-1)){
flag = true;
root = create(true, 0, n-1);
}else if(test(false, 0, n-1)){
flag = true;
root = create(false, 0, n-1);
}
if(flag){
cout<<"YES"<<endl;
postTraverse(root);
int len = v.size();
for(int i=0; i<len; i++){
if(i==0){
cout<<v[i];
}else {
cout<<" "<<v[i];
}
}
cout<<endl;
}else {
cout<<"NO"<<endl;
}
return 0;
}