pat1043
1.题目大意
给定一个前序序列,来进行判断是否完全二叉树。
2.思路
对整个序列进行排序,因为完全二叉树中序遍历就是排好序了的。所以我们根据前序和中序看是否能够建树,如果不行,那就对前序进行翻转,再次重建,看是否可以,如果还是不行,那么就是真的无法建树。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ivfbAMN3-1639230724755)(https://files.catbox.moe/zxdj23.png)]
建树过程,如果是正常的,那就是正常建树。如果不是就首先对前序进行翻转,从后往前钱开始查找根节点来建树
bool build(int il,int ir, int pl,int pr,int type){
if(il>ir){
return true;
}
int root=preorder[pl];
// 寻找root
int k;
if(type==0){
// 没有反转
k=0;
for(k = il; k <= ir; k++)
{
if(inorder[k] == root)
break;
}
if (k>ir){
return false;
// 无法构建
}
} else{
// 反转了,就是,从后往前找
for(k = ir; k >= il; k--)
{
if(inorder[k] == root)
break;
}
if(k < il) return false;
}
bool ans= true;
if(!build(il, k - 1, pl + 1, pl + 1 + (k - 1 - il), type)) ans = false;
if(!build(k + 1, ir, pl + 1 + (k - 1 - il) + 1, pr, type)) ans = false;
// 这就是后续了,先左,再右,最后post【cnt
postorder[cnt++]=root;
return ans;
}
同时还有后续遍历,后续遍历,就是咋爱最后一次进行操作,可以直接插入到建树的过程里。
postorder[cnt++]=root;
3.代码实现
#include <cstring>
#include <iostream>
#include <algorithm>
#include "unordered_map"
#include "queue"
using namespace std;
const int N = 10010,M=2*N;
int preorder[N];
int inorder[N];
int postorder[N];
int cnt=0;
//jilu当前的
//重建二叉树,type是是否精选
bool build(int il,int ir, int pl,int pr,int type){
if(il>ir){
return true;
}
int root=preorder[pl];
// 寻找root
int k;
if(type==0){
// 没有反转
k=0;
for(k = il; k <= ir; k++)
{
if(inorder[k] == root)
break;
}
if (k>ir){
return false;
// 无法构建
}
} else{
// 反转了,就是,从后往前找
for(k = ir; k >= il; k--)
{
if(inorder[k] == root)
break;
}
if(k < il) return false;
}
bool ans= true;
if(!build(il, k - 1, pl + 1, pl + 1 + (k - 1 - il), type)) ans = false;
if(!build(k + 1, ir, pl + 1 + (k - 1 - il) + 1, pr, type)) ans = false;
// 这就是后续了,先左,再右,最后post【cnt
postorder[cnt++]=root;
return ans;
}
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 (build(0,n-1,0,n-1,0)){
// 正藏构建
puts("YES");
cout << postorder[0];
for(int i = 1; i < n; i++)
cout << " " << postorder[i];
} else{
// 进行反转
reverse(inorder,inorder+n );
//从大到小,这样就,pre也是从大到小,那么就可以先确定左子树生成
cnt = 0;
if(build(0, n-1, 0, n-1, 1))
{
puts("YES");
cout << postorder[0];
for(int i = 1; i < n; i++)
cout << " " << postorder[i];
}
else
cout << "NO";
}
cout << endl;
return 0;
}