题目
Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.
输入
Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.
输出
For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.
样例输入
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
样例输出
4 1 6 3 5 7 2
题意理解
给你n个节点
先输入二叉树的后序遍历,再输入中序遍历
最后让你求层序遍历
那么我们直接建树,然后bfs一遍就能得到树的层序遍历
注意到中序遍历是 左 根 右 后序遍历是 左 右 根
那么我们存一下中序遍历每个点的位置是多少,中序遍历就是我们划分左右子树的关键
而后序遍历能帮我们确定哪个是根,没错,就是最后一个就是根节点
先构建树
il是中序遍历左端点 ir右端点
pl是后序遍历左端点 pr右端点
我们的根节点就是后序遍历的右端点 因为后序是 左右根 最后一个一定是这颗子树的根节点
然后我们找到根节点在中序遍历中的位置 我们根据根节点 来划分左右子树
如果此时根节点的位置k大于中序遍历的左端点 ,那么说明我们还没到左边的边界
此时我们还可以构建左子树
那么我们递归构建左子树 注意这里构建传入的边界
il 中序左端点 k-1右端点(中序根节点的左边一个位置)pl后序遍历左端点
那么左子树的后序遍历右边界在哪呢
我们注意到因为中序的左子树长度等于后序左子树的长度 所以
k-1-il这就是中序遍历中左子树的长度
根节点-1再-中序遍历的左端点
这个长度加上pl就是后序遍历的右边界
所以左子树建树为
build(il,k-1,pl,k-il-1+pl)
右子树同样我们也递归建树
k+1 根节点右边一个位置就是右子树的中序左端点
ir 右端点
k-1-il之前我们已经分析过这是中序遍历中左子树的长度加上pl就是左子树的边界
那么我们再加一 就是右子树的左边界了
pr-1就是我们后序根节点的前一个位置,此时这个位置是下一个右子树的根节点
所以右子树建树为
build(k+1,ir,k-il-1+pl+1,pr-1)
此时建立完整棵树了,那么我们跑一遍bfs就能获得这棵树的层序遍历了
代码
#include<bits/stdc++.h>
using namespace std;
const int N=35;
unordered_map<int,int> pos;
unordered_map<int,int> l,r;
int postorder[35];//后序
int inorder[35];//中序
int n;
vector<int>ve;
int build(int il,int ir,int pl,int pr){
int root=postorder[pr];
int k=pos[root];
if(k>il)l[root]=build(il,k-1,pl,k-il-1+pl);
if(k<ir)r[root]=build(k+1,ir,k-il-1+pl+1,pr-1);
return root;
}
void bfs(int root){
queue<int>q;
q.push(root);
while(q.size()){
int t=q.front();
q.pop();
ve.push_back(t);
if(l.count(t))q.push(l[t]);
if(r.count(t))q.push(r[t]);
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>postorder[i];
}
for(int i=0;i<n;i++){
cin>>inorder[i];
pos[inorder[i]]=i;
}
int root=build(0,n-1,0,n-1);
bfs(root);
for(int i=0;i<ve.size();i++){
if(i)printf(" ");
printf("%d",ve[i]);
}
puts("");
return 0;
}