题目描述
原题
大概意思就是给你一个序列,可能是前序遍历序列(左根右)或者是镜像前序遍历序列(右根左),让你判断是不是有效的遍历序列,并且输出这棵树后序遍历序列
思路
- 方法1:先用插入法利用所给序列构造树,再判断正确的前序序列或者镜像前序序列与所给序列是否一致
- 代码较多,过程比较繁琐
- 方法2:利用二叉搜索树的性质:递增排序后的结点顺序就是中序遍历序列,而知道中序和前序就能创建一棵树
AC代码(方法2)
#include<bits/stdc++.h>
using namespace std;
int preOrder[1010],inOrder[1010];
int postOrder[1010];
int Index; //存储后序遍历序列的数组的下标
/* 前序与中序遍历构造树 */
bool buildTree(int ps, int pe, int is, int ie){
//结束条件
if(ps>pe) return true;
int root = preOrder[ps];
//假定给的是前序序列 判断其是否合法
int pos = -1;
for(int i = is;i<=ie;++i){
if(inOrder[i]==root){
pos = i;
break;
}
}
if(pos == -1) return false;
int leftLen = pos-is;
int rightLen = ie-pos;
//构建左子树
if(!buildTree(ps+1,ps+leftLen, is,pos-1)) return false;
//构建右子树
if(!buildTree(pe-rightLen+1,pe, pos+1,ie)) return false;
postOrder[Index++] = root;
return true;
}
/* 镜像前序和中序构造树 */
bool buildTreeMirr(int ps, int pe, int is, int ie){
//结束条件
if(ps>pe) return true;
int root = preOrder[ps];
//假定给的是镜像前序序列 判断其是否合法
int pos = -1;
for(int i = is;i<=ie;++i){
if(inOrder[i]==root){
pos = i;
break;
}
}
if(pos == -1) return false;
int leftLen = pos-is;
int rightLen = ie-pos;
//构建右子树 !注意顺序
if(!buildTreeMirr(ps+1,pe-leftLen,pos+1,ie)) return false;
//构建左子树
if(!buildTreeMirr(ps+rightLen+1,pe,is,pos-1)) return false;
postOrder[Index++] = root;
return true;
}
int main(){
int N;
cin>>N;
for(int i = 0;i<N;++i){
cin>>preOrder[i];
inOrder[i] = preOrder[i];
}
sort(inOrder,inOrder+N); //升序排列
if(buildTree(0,N-1,0,N-1)||buildTreeMirr(0,N-1,0,N-1)){
cout<<"YES"<<endl;
cout<<postOrder[0];
for(int j=1;j<N;++j)
cout<<" "<<postOrder[j];
}else
cout<<"NO"<<endl;
return 0;
}