题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805070971912192
类似题目有FBI树
这两个题有个小技巧,就是建树时是前序遍历,只要将输出放在递归调用之后就是后序遍历了,仔细思考下就能够想明白
对前中后序不熟的记住前中后都是形容跟的次序,左永远在右的前面
建树的时候注意左子树遍历时有i<=r,右子树却只是j>l而没有等号,那是因为可能一个序列只有左子树,所以左子树遍历必须包括所有,而有右子树就肯定有左子树了,就不需要包含了,另外仔细读题,
二叉搜索树的等于号是在右子树(镜像就是左子树)
一开始设不是镜像跑一次,向量大小不为n就清空在按照是镜像跑一次
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf=1<<30; 4 typedef long long ll; 5 typedef pair<int,int> P; 6 const double pi=acos(-1); 7 const int mod=1e8+7; 8 const int maxn=1007; 9 const int maxm=6300; 10 int a[maxn]; 11 bool is_mirror; 12 vector<int> v; 13 void maketree(int l,int r){ 14 if(l>r) return ; 15 int i=l+1,j=r;//因为是前序遍历,开头第一个是根,此时i在左子树,j在右子树 16 if(!is_mirror){ 17 while(i<=r&&a[l]>a[i]) i++;//非镜像左子树都比根小,循环结束把左子树遍历完后i跑到右子树的第一个 18 while(j>l&&a[j]>=a[l]) j--; 19 }else{ 20 while(i<=r&&a[l]<=a[i]) i++; 21 while(j>l&&a[j]<a[l]) j--; 22 } 23 if(i-j!=1) return ; 24 maketree(l+1,j);//左子树 25 maketree(i,r);//右子树 26 v.push_back(a[l]);//按照前序建树,递归后在输出就是后序了,可以仔细想想,类似题有FBI树 27 } 28 int main(){ 29 int n;scanf("%d",&n); 30 for(int i=0;i<n;i++)scanf("%d",&a[i]); 31 maketree(0,n-1); 32 if(v.size()!=n){ 33 is_mirror=1; 34 v.clear(); 35 maketree(0,n-1); 36 } 37 if(v.size()==n){ 38 printf("YES %d",v[0]); 39 for(int i=1;i<n;i++)printf(" %d",v[i]); 40 cout<<endl; 41 }else{ 42 printf("NO "); 43 } 44 return 0; 45 }