题目: https://pintia.cn/problem-sets/15/problems/843
对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。
现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。
输入格式:
输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,数字间以空格分隔。
输出格式:
输出的第一行首先给出判断结果,如果输入的序列是某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,则输出YES
,否侧输出NO
。如果判断结果是YES
,下一行输出对应二叉树的后序遍历序列。数字间以空格分隔,但行尾不能有多余的空格。
输入样例1:
7
8 6 5 7 10 8 11
输出样例1:
YES
5 7 6 8 11 10 8
输入样例2:
7
8 6 8 5 10 9 11
输出样例2:
NO
对于给定的n个数,令第一个数a0为根结点,查找比a0大的结点ai,再遍历ai的右边是否存在比a0小的结点,若存在则该树不为搜索树。ai结点及其之后的结点为a0的右子树,a0+1到ai-1的结点为a0的左子树,并重复上述过程;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef int type;
#define MAX 1005
int f1,f2;
int f=0;
typedef struct tree{
struct tree *left,*right;
int num;
}tree,*ptree;
ptree Create(int a[],int n){
if(!n) return NULL;
ptree pt=(ptree)malloc(sizeof(tree));
pt->num=*a;
int i,j;
for(i=1;i<n;i++){
if(a[i]>=pt->num)
break;
}
for(j=i;j<n;j++){
if(a[j]<pt->num){
f1=1;
return NULL;
}
}
pt->left=Create(a+1,i-1);
pt->right=Create(a+i,n-i);
return pt;
}
ptree CreateMirror(int a[],int n){
if(!n) return NULL;
ptree pt=(ptree)malloc(sizeof(tree));
pt->num=*a;
int i,j;
for(i=1;i<n;i++){
if(a[i]<pt->num)
break;
}
for(j=i;j<n;j++){
if(a[j]>=pt->num){
f2=1;
return NULL;
}
}
pt->left=CreateMirror(a+1,i-1);
pt->right=CreateMirror(a+i,n-i);
return pt;
}
void Show(ptree pt){
if(pt){
Show(pt->left);
Show(pt->right);
if(!f)
f=1;
else printf(" ");
printf("%d",pt->num);
}
}
int main(){
int n;
int a[MAX];
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
ptree pt=Create(a,n);
ptree ppt=CreateMirror(a,n);
if(pt&&!f1){
printf("YES\n");
Show(pt);
printf("\n");
}
else if(ppt&&!f2){
printf("YES\n");
Show(ppt);
printf("\n");
}
else printf("NO\n");
}