L2-011 玩转二叉树

L2-011传送门

这道题与前面的一道题几乎一样😁(*^▽^*)

唯一有变化的就是镜像翻转

  1. 那我们只需要先建右子树,再建左子树就行了。
  2. 或者我们可以正常建树,但是在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;
}
posted @ 2026-03-15 10:02  shuiwangrenjia  阅读(20)  评论(0)    收藏  举报