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;
}
posted @ 2019-09-03 17:02  YuhanのBlog  阅读(77)  评论(0编辑  收藏  举报