題目: 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");
}