L2-006 树的遍历

题目链接:https://pintia.cn/problem-sets/994805046380707840/exam/problems/type/7?problemSetProblemId=994805069361299456&page=1

题意:

给定一个二叉树的后序以及中序遍历序列,求其层序遍历序列(bfs次序)

思路:

对于二叉树用数组模拟,若一个节点在数组位置中为u,则其左儿子在数组中的位置为u<<1,右儿子u<<1|1
解决序列遍历问题,套路递归
即每次递归解决一个左子树问题,再去递归解决一个右子树问题
(因此dfs递归传参需要子树在数组中的l和r)
(套路当传参l>r时,需要return(叶子节点的叶节点))

对于本题
后序遍历在左端点l1,右端点r1的子树上时,a[r1]即为该子树的根节点
中序遍历在左端点l2,右端点为r2的子树上时,[l2,pos-1]为该根节点的左子树,[pos+1,r2]为该根节点的右子树
(pos代表根节点在中序遍历序列中的位置)
不难发现其根节点 左子树的大小为pos-l2 右子树的大小为 r2-pos
再回到后序遍历就可以推出[l1,l1+pos-l2-1]为左子树区间,[l1+pos-l2,r1-1]

不断递归建立起二叉树即可

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int b[maxn];
//vector<int>e[maxn];
int tr[maxn];
void dfs(int u,int l1,int r1,int l2,int r2){
	if(l1>r1||l2>r2){
		tr[u]=-1;return;
	}
	
	int root=a[r1];int pos;
	
	for(int i=l2;i<=r2;i++){
		if(b[i]==root){
			pos=i;break;
		}
	}
	
	int len=pos-l2;
	
	tr[u]=root;
	dfs(2*u,l1,l1+len-1,l2,pos-1);
	dfs(2*u+1,l1+len,r1-1,pos+1,r2);
}
void bfs(){
	queue<int>q;
	q.push(1);
	while(q.size()){
		int cur=q.front();q.pop();
		if(tr[cur]==-1||tr[cur]==0)continue;
		if(tr[cur<<1]!=-1&&tr[cur<<1]!=0)q.push(cur<<1);
		if(tr[cur<<1|1]!=-1&&tr[cur<<1|1]!=0)q.push(cur<<1|1);
		cout<<tr[cur];
		if(q.size())cout<<' '; 
	}
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
	}
	dfs(1,1,n,1,n);
	bfs();
	return 0;
}
posted @ 2025-04-18 22:03  Marinaco  阅读(19)  评论(0)    收藏  举报
//雪花飘落效果