【PAT甲级】1119 Pre- and Post-order Traversals (30分)(已知先序后序输出是否二叉树唯一并输出中序遍历)
题意:
输入一个正整数N(<=30),接着输入两行N个正整数第一行为先序遍历,第二行为后续遍历。输出是否可以构造一棵唯一的二叉树并输出其中一颗二叉树的中序遍历。
trick:
输出完毕中序遍历后须换行,否则所有测试点格式错误。
1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 int pre[37],post[37]; 5 map<int,int>mp; 6 int flag; 7 vector<int>ans; 8 void dfs(int prel,int prer,int postl,int postr){//先序遍历起点,先序遍历终点,后序遍历起点,后序遍历终点 9 if(prel==prer){//根节点 10 ans.emplace_back(pre[prel]); 11 return ; 12 } 13 int x=mp[post[postr-1]];//找到后序遍历中根节点前一个结点在先序遍历中的位置,这个结点即为右子树的根节点 14 if(x-prel>1){//存在左子树 15 dfs(prel+1,x-1,postl,postl+x-prel-2);//划分左子树 16 //先序遍历中:左子树起点为去掉根节点,左子树终点为先序遍历中右子树根节点前一个结点; 17 //后序遍历中:左子树起点不变,左子树终点为起点加上先序遍历中终点和起点的差 18 ans.emplace_back(pre[prel]);//左子树的根节点 19 dfs(x,prer,postl+x-prel-2+1,postr-1);//划分右子树 20 //先序遍历中:右子树起点为x,右子树终点为最后一个结点; 21 //后序遍历中:右子树起点为左子树终点+1,右子树终点为去掉根节点 22 } 23 else{//不存在左子树,那么这个结点可以作为左右结点任一,构造结果因此不唯一 24 flag=1;//标记 25 ans.emplace_back(pre[prel]);//子树的根节点 26 dfs(x,prer,postl+x-prel-2+1,postr-1);//把剩余结点当作右子树,处理方法和划分右子树相同 27 } 28 } 29 int main(){ 30 ios::sync_with_stdio(false); 31 cin.tie(NULL); 32 cout.tie(NULL); 33 int n; 34 cin>>n; 35 for(int i=1;i<=n;++i){ 36 cin>>pre[i]; 37 mp[pre[i]]=i;//记录点序号在先序遍历中出现的位置 38 } 39 for(int i=1;i<=n;++i) 40 cin>>post[i]; 41 dfs(1,n,1,n);//对先序遍历进行分割 42 if(flag==0) 43 cout<<"Yes\n"; 44 else 45 cout<<"No\n"; 46 cout<<ans[0]; 47 for(int i=1;i<ans.size();++i) 48 cout<<" "<<ans[i]; 49 cout<<"\n"; 50 return 0; 51 }
保持热爱 不懈努力
不试试看怎么知道会失败呢(划掉)
世上无难事 只要肯放弃(划掉)