题目
思路一:
由于中序序列加前或后序列能唯一确定一个树,那就把这个树建出来,再用bfs一层一层遍历
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
struct Node {
int val,l,r;
} node[MAX];
int tot;
int c[MAX],b[MAX];
int dfs(int len,int b[],int c[]) {//中序,后序
if(len <= 0) return -1;
if(len == 1) {
node[++tot].val = b[1];
node[tot].l=node[tot].r = -1;
return tot;
}
node[++tot].val = c[len];
int res = tot;
int l;
for(l = 1; l<=len; l++) {
if(b[l] == c[len]) break;
}
node[res].l = dfs(l-1,b,c);
//node[res].r = dfs(len-l,b+l-1,c+l);
node[res].r = dfs(len-l,b+l,c+l-1);
return res;
}
void bfs() {
queue<int> q;
q.push(1);
while(q.size()) {
int cur = q.front();q.pop();
if(cur != 1) printf(" ");
printf("%d",node[cur].val);
if(node[cur].l != -1) q.push(node[cur].l);
if(node[cur].r != -1) q.push(node[cur].r);
}
}
int main()
{
int n;
cin>>n;
for(int i = 1; i<=n; i++) scanf("%d",c+i);
for(int i = 1; i<=n; i++) scanf("%d",b+i);
dfs(n,b,c);
//printf("%d",node[1].val);
bfs();
return 0 ;
}
思路二:
不把树建出来,在遍历树的时候给树的深度也表示出来,最后把节点按深度排序,然后输出
我们根据后序序列的性质发现一个规律,就是后序序列从左到右,当一个节点的相邻左边的节点可能是这个节点的右孩子(当且仅当它的右孩子存在时),可能是这个节点的左孩子(当且仅当右孩子不存在,左孩子存在时)。
而我们可以根据后序序列的最后一个值来找到中序序列中的中间节点,跟距中序序列提供的区间范围来判断这个节点的孩子是否存在
这个性质也可以帮助大家根据两个序列来快速画出二叉树的图,大家不妨一试。
以下代码就是利用分治的方法,分治中序序列中的左右子树,其间根据dfs的层数来判断深度
最后由于我们是先右再左的方式遍历,而一般的层次遍历是从左往右,需要先用冒泡排序按深度排序(稳定)
得到从右往左的序列,之后每层倒着输出。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
const int N = 33;
int back[N],mid[N];
int n,t;
vector<pair<int,int> >deep;
//递归出口是区间长度为0
void erfen(int i,int j,int cnt)
{
if(i>j||i<1||j>n) return;
int x=back[t--],middle=-1;
deep.push_back({cnt+1,x});//
int k;
for( k=i;k<=j;k++)
if(mid[k]==x)
{middle=k;
break;}
if (middle==-1) return;
erfen(middle+1,j,cnt+1);
erfen(i,middle-1,cnt+1);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>back[i];//找出节点深度,排序后输出
for(int i=1;i<=n;i++) cin>>mid[i];
t=n;
erfen(1,n,0);
int leng=deep.size();
for(int i=0;i<leng-1;i++)
{
for(int j=0;j<leng-1-i;j++)
{
int x=deep[j].first,y=deep[j+1].first;
if(x>y)
{
int t=x;
deep[j].first=deep[j+1].first;
deep[j+1].first=t;
t=deep[j].second;
deep[j].second=deep[j+1].second;
deep[j+1].second=t;
}
}
}
int flag=0;
for (int i = 0; i <n; i ++ )
{
int j=i;
while(deep[j+1].first==deep[j].first) j++;
for (int k = j; k>= i; k -- )
if(!flag)
{
cout<<deep[k].second;
flag=1;
}
else cout<<' '<<deep[k].second;
i=j;
}
}
/*7
4 5 3 7 6 2 1
5 3 4 1 7 2 6*/