PAT 甲级 1119 Pre- and Post-order Traversals (30 分)
思路:
1.用两个vector存储前根和后根遍历序列,同时用map存储每一个value在后根遍历序列中的位置;
2.前序和后序不能确定唯一一颗二叉树的原因是,如果当前结点只有一个孩子,它不能分清这是左孩子还是右孩子;
3.每次递归,前序的第一个和后序的最后一个就是当前结点,前序的第二个结点是当前结点的孩子结点,查询前序第二个结点在后序中的位置,若在倒数第二个位置,那当前结点只有一个孩子,设置标志“唯一”为false,你可以将这个不确定的作为左孩子或者右孩子(都可以);
4.最后递归实现中根遍历;
代码:
#include<iostream>
#include<vector>
#include<map>
using namespace std;
map<int,int> lca;
vector<int> pre,post,in;
map<int,pair<int,int>> tree;
bool flag=true;
void buildTree(int st1,int ed1,int st2,int ed2){
if(ed1<=st1) return;
tree[pre[st1]].first=pre[st1+1];
buildTree(st1+1,lca[pre[st1+1]]-st2+st1+1,st2,lca[pre[st1+1]]);
if(lca[pre[st1+1]]==ed2-1) flag=false;
else{
tree[pre[st1]].second=post[ed2-1];
buildTree(ed1+lca[pre[st1+1]]+2-ed2,ed1,lca[pre[st1+1]]+1,ed2-1);
}
}
void inOrder(int root){
if(tree[root].first!=0) inOrder(tree[root].first);
in.push_back(root);
if(tree[root].second!=0) inOrder(tree[root].second);
}
int main(){
int n;
scanf("%d",&n);
pre.resize(n);
post.resize(n);
for(int i=0;i<n;i++) scanf("%d",&pre[i]);
for(int i=0;i<n;i++){
scanf("%d",&post[i]);
lca[post[i]]=i;
}
buildTree(0,n-1,0,n-1);
printf(flag==true?"Yes\n":"No\n");
inOrder(pre[0]);
for(int i=0;i<n;i++) printf(i==0?"%d":" %d",in[i]);
printf("\n");
return 0;
}