已知二叉树的前序和中序遍历求后序遍历

假设二叉树上各结点的权值互不相同且都为正整数。

给定二叉树的前序遍历和中序遍历,请你输出二叉树的后序遍历序列。

输入格式

第一行包含整数 N,表示二叉树结点总数。

第二行给出二叉树的前序遍历序列。

第三行给出二叉树的中序遍历序列。

输出格式

输出二叉树的后序遍历的第一个数字。

数据范围

1≤N≤50000

输入样例:

7
1 2 3 4 5 6 7
2 3 1 5 4 7 6

输出样例:

3 2 5 7 6 4 1

题解:

已知树的先序遍历的第一个元素就是树(子树)的根节点

重复下面操作就可以构建一个树了

  • 找先序中第一个数,再看该数在中序遍历中的位置
  • 中序位置的左边的数就在该数的左子树上, 右边的数就在该数的右子树上
  • 再看该数的先序中 左子树上的数离该数最近的 和 右子树上的数离该数最近的 , 这两个离得最近得数就是该数的左右子树的根节点

代码解读
代码中的build函数传递的是 先序和后序序列的左右闭区间
找到左右子树的左右闭区间, 每次取先序的第一个数就可以完成上述重复操作,构建出完整的树
最后用print函数, 输出后序序列

先序的左右闭区间不会找的话看下面的图 👇 (ps :为什么有图中的等式: 因为先序和中序的闭区间中的元素个数是相同的)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N];
unordered_map<int,int> l, r, c;
int build(int al, int ar, int bl, int br) // a 是先序, b 是中序
{
int root = a[al];
int k = c[root]; // 👇 x
if (k > bl) l[root] = build(al + 1, k - bl + al, bl, k - 1);
if (k < br) r[root] = build(k - bl + al + 1, ar, k + 1, br);
return root; // 👆 x + 1
}
int n;
void print(int root)
{
if (l[root] != 0) print(l[root]);
if (r[root] != 0) print(r[root]);
cout << root << ' ';
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
for (int i = 0; i < n; i ++)
{
cin >> b[i]; c[b[i]] = i;
}
int root = build(0, n - 1, 0, n -1);
print(root);
return 0;
}

觉得写的不错的话,点个赞吧!~

posted @   小lii  阅读(252)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
点击右上角即可分享
微信分享提示