给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
4 1 6 3 5 7 2
前置知识,已知二叉树的前序,中序可以求后序,已经后序中序可以求前序,但是给定前序和后序不能确定中序。
洛谷上有一道已知前序后序求所有不同的中序二叉树可能序列个数的题
P1229 遍历问题
看了y总的提示,自己写出来了很nice
#include
#include
#define debug(x) cout<<#x<<":"<<x<<endl
using namespace std;
const int N = 50;
int a[11000],n,cnt;
int in[N],p[N];
map<int,int>mp;
int lson[N],rson[N];
void dfs(int P,int inl,int inr,int pl,int pr){//用类似线段树建树的思想。
if(inl>inr||pl>pr)return ;
int root = p[pr];
int idx = mp[root];
// idx - pl 是左子树节点的个数。
dfs(P*2,inl,idx-1,pl,pl+idx-inl-1);
dfs(P*2+1,idx+1,inr,pl+idx-inl,pr-1);
cnt++;
a[P]=root;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=n;i++){
cin>>in[i];
mp[in[i]]=i;
}
dfs(1,1,n,1,n);
// debug(cnt);
bool flag=0;
// 我的写法有一个bug,如果这颗树是一条链的话,数组是开不下的,还好PTA数据水。
for(int i=1;i<=10000;i++){
if(!a[i])continue;
if(!flag){
cout<<a[i];
flag=1;
}
else{
cout<<" "<<a[i];
}
}
}
把代码改改,不传递第一个idx就变成了已知后序中中序求前序的题。
#include
#include
#define debug(x) cout<<#x<<":"<<x<<endl
using namespace std;
const int N = 50;
int a[N],n,cnt;
int in[N],p[N];
map<int,int>mp;
int lson[N],rson[N];
//前序遍历了
int dfs(int inl,int inr,int pl,int pr){
if(inl>inr||pl>pr)return ;
int root = p[pr];
int idx = mp[root];
a[++cnt]=root;
debug(root);
debug(idx);
// idx - pl 是左子树节点的个数。
int lson = dfs(inl,idx-1,pl,pl+idx-inl-1);
int rson = dfs(idx+1,inr,pl+idx-inl,pr-1);
return root;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=n;i++){
cin>>in[i];
mp[in[i]]=i;
}
dfs(1,n,1,n);
bool flag=0;
for(int i=1;i<=cnt;i++){
if(!flag){
cout<<a[i];
flag=1;
}
else{
cout<<" "<<a[i];
}
}
}
y总直接用hash表存每个节点的儿子是谁,这样就可以O(N)了。
#include
#include
#include
#include
#define debug(x) cout<<#x<<":"<<x<<endl
using namespace std;
const int N = 50;
int n;
int in[N],p[N],root;
unordered_map<int,int>mp,lson,rson;
int dfs(int inl,int inr,int pl,int pr){//用类似线段树建树的思想。
int root = p[pr];
int idx = mp[root];
// idx - pl 是左子树节点的个数。
if(inl<idx)
lson[root] = dfs(inl,idx-1,pl,pl+idx-inl-1);
if(idx<inr)
rson[root] = dfs(idx+1,inr,pl+idx-inl,pr-1);
return root;
}
void bfs(int S){
bool flag=1;
queue<int>que;
que.push(S);
while(que.size()){
auto t = que.front();
que.pop();
if(flag){
cout<<t;
flag=0;
}
else{
cout<<" "<<t;
}
if(lson.count(t)){//不是lson[t].count(),别记错了
que.push(lson[t]);
}
if(rson.count(t)){
que.push(rson[t]);
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=n;i++){
cin>>in[i];
mp[in[i]]=i;
}
root = dfs(1,n,1,n);
bfs(root);
}
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
输入第一行给出一个正整数N
(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
4 6 1 7 5 3 2
我是在bfs里边实现了一下翻转,有点麻烦,能A就行。
#include
#include
#include
#include
#include
#define debug(x) cout<<#x<<":"<<x<<endl
using namespace std;
const int N = 50;
int n,pre[N],in[N];
unordered_map<int,int>h,lson,rson;
int root;
int dfs(int inl,int inr,int pl,int pr)
{
int root = pre[pl];
int idx = h[root];
if(idx>inl)
lson[root]=dfs(inl,idx-1,pl+1,pl+idx-inl);
if(idx<inr)
rson[root]=dfs(idx+1,inr,pl+idx-inl+1,pr);
return root;
}
void bfs(int S){
queue<int>que;
que.push(S);
bool flag=1;
while(que.size()){
auto t = que.front();
que.pop();
if(flag){
flag=0;
cout<<t;
}
else{
cout<<" "<<t;
}
//输出的时候反转一下,感觉实现的有点麻烦
if(lson.count(t)&&rson[t]){
que.push(rson[t]);
}
else if(rson.count(t)&&rson[t]){
que.push(rson[t]);
}
if(rson.count(t)&&lson[t]){
que.push(lson[t]);
}
else if(lson.count(t)&&lson[t]){
que.push(lson[t]);
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>in[i],h[in[i]]=i;
for(int i=1;i<=n;i++)cin>>pre[i];
root = dfs(1,n,1,n);
bfs(root);
}
学到了另一种要求输出层序遍历的方法,在dfs中加入深度,因为dfs按照根左右的顺序,顺便就把层序遍历序列记录下来了。
int n;
int a[35];
int get(int l,int r){ // 求[l,r]最小元素下标
int res = l;
for(int i=l;i<=r;i++){
if(a[i] < a[res]){
res = i;
}
}
return res;
}
vector<int>ans[40];
void dfs(int l,int r,int u){
if(u>=n || l>r)return ;
int pos = get(l,r);//
int tar = a[pos];
ans[u].pb(tar);
dfs(l,pos-1,u+1);
dfs(pos+1,r,u+1);
}
void solve(){
cin>>n;
fo(i,1,n){
cin>>a[i];
}
dfs(1,n,1);
for(int i=1;ans[i].size();i++){
for(auto c:ans[i]){
cout<<c<<" ";
}
}
}
int main(){
solve();
return 0;
}