L2-011 玩转二叉树
这道题与前面的一道题几乎一样😁(*^▽^*)
唯一有变化的就是镜像翻转
- 那我们只需要先建右子树,再建左子树就行了。
- 或者我们可以正常建树,但是在BFS的时候 , 先让右边入队,再让左边入队。
你会选择哪一个呢?
实际上,选择第一点最好,因为第二点并没有真正的建树,很多时候,我们必须要在内存上做出改变才行啊。
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;
int pre[10010], in[10010];
unordered_map<int, int> l, r, pos;
int build(int inL, int inR, int preL, int preR)
{
//如果当前节点的某个子节点不存在就返回0.
if (inL > inR)
{
return 0;
}
int root = pre[preL];
int k = pos[root];
int num = k - inL;
// 【核心翻转逻辑】
// 原本 build(inL, k - 1, ...) 是左子树,现在赋值给 r[root]
// 原本 build(k + 1, inR, ...) 是右子树,现在赋值给 l[root]
// 这样在树的物理结构上,左右就彻底颠倒了
r[root] = build(inL, k - 1, preL + 1, preL + num);
l[root] = build(k + 1, inR, preL + num + 1, preR);
return root;
}
void bfs(int root)
{
if (root == -1) return;
queue<int> q;
q.push(root);
bool first = true;
while (!q.empty())
{
int now = q.front();
q.pop();
if (!first) cout << " ";
cout << now;
first = false;
// 既然建树时已经翻转,这里依然按照标准【先左后右】入队
// 此时输出的就是镜像后的层序
//注意了: 这里判断其不为0并不是因为,初始默认值为0,而是我们上面将不存在的子节点赋值为0
if (l[now] != 0) q.push(l[now]);
if (r[now] != 0) q.push(r[now]);
}
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> in[i];
for (int i = 0; i < n; i++)
{
cin >> pre[i];
}
for (int i = 0; i < n; i++) pos[in[i]] = i;
int root = build(0, n - 1, 0, n - 1);
bfs(root);
cout << endl;
return 0;
}

浙公网安备 33010602011771号