题意
- 给出一棵树的前序遍历或者镜像的前序遍历,判断是否是二叉树,如果是,输出后序遍历。
题解
- 如果是一棵二叉树,那么通过前序+中序可以构建,中序升序排列。
- 最后判断二叉树是否完整以及叶子的大小是否符合规则
- 对于镜像,中序是降序。用同样的方式实现。
代码
#include <bits/stdc++.h>
using namespace std;
int const N = 1000 + 10;
int pre[N],post[N],in[N],n,pos,id;
vector<int>ans;
struct Node{
int left,right;
int val;
}node[N];
int dfs(int l,int r){ //pos表示pre的位置
if(l > r) return -1;
int mid = -1;
for(int i=l;i<=r;i++){
if(pre[pos] == in[i]){
mid = i;
break;
}
}
if(mid == -1) return -1; //来判断是否可以成树
int tid = id++;
node[tid].val = pre[pos++];
node[tid].left = dfs(l,mid - 1);
node[tid].right = dfs(mid + 1,r);
ans.push_back(node[tid].val);
return tid;
}
int mdfs(int l,int r){ //pos表示pre的位置
if(l > r) return -1;
int mid = -1;
for(int i=l;i<=r;i++){
if(pre[pos] == in[i]){ //这里不用break
mid = i;
}
}
if(mid == -1) return -1;
int tid = id++;
node[tid].val = pre[pos++];
node[tid].left = dfs(l,mid - 1);
node[tid].right = dfs(mid + 1,r);
ans.push_back(node[tid].val);
return tid;
}
bool judge(int root){
int l = node[root].left, r = node[root].right;
if(l != -1 && node[l].val > node[root].val) return false;
if(r != -1 && node[r].val <= node[root].val) return false;
if(l != -1 && !judge(l)) return false;
if(r != -1 && !judge(r)) return false;
return true;
}
bool mjudge(int root){
int l = node[root].left, r = node[root].right;
if(l != -1 && node[l].val < node[root].val) return false;
if(r != -1 && node[r].val >= node[root].val) return false;
if(l != -1 && !mjudge(l)) return false;
if(r != -1 && !mjudge(r)) return false;
return true;
}
bool solve1(){
sort(in + 1,in + 1 + n);
id = pos = 1;
dfs(1,n); //由pre+in构造二叉树
if(judge(1) && ans.size() == n){ //ans.size() == n表示后序遍历完整
printf("YES\n");
for(int i=0;i<ans.size();i++){
printf("%d%c",ans[i],i == ans.size() - 1 ? '\n' : ' ');
}
return true;
}
return false;
}
bool solve2(){
reverse(in + 1,in + 1 + n); //镜像的中序遍历大小变换
id = pos = 1;
ans.clear();
mdfs(1,n);
if(mjudge(1) && ans.size() == n){
printf("YES\n");
for(int i=0;i<ans.size();i++){
printf("%d%c",ans[i],i == ans.size() - 1 ? '\n' : ' ');
}
return true;
}
return false;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&pre[i]);
in[i] = pre[i];
}
if(!solve1()){
if(!solve2())
printf("NO\n");
}
return 0;
}