• 重建二叉树


    重建二叉树

    输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树。

    注意

    • 二叉树中每个节点的值都互不相同;
    • 输入的前序遍历和中序遍历一定合法;

    数据范围

    树中节点数量范围 [ 0 , 100 ] [0,100] [0,100]

    样例

    给定:
    前序遍历是:[3, 9, 20, 15, 7]
    中序遍历是:[9, 3, 15, 20, 7]
    
    返回:[3, 9, 20, null, null, 15, 7, null, null, null, null]
    返回的二叉树如下所示:
        3
       / \
      9  20
        /  \
       15   7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    算法

    (递归) O ( n ) O(n) O(n)

    递归建立整棵二叉树:先递归创建左右子树,然后创建根节点,并让指针指向两棵子树。

    具体步骤如下:

    1. 先利用前序遍历找根节点:前序遍历的第一个数,就是根节点的值;
    2. 在中序遍历中找到当前根节点的位置 k k k ,则 k k k 左边是左子树的中序遍历``,右边是右子树的中序遍历;
    3. 假设左子树的中序遍历的长度是 l l l ,则在前序遍历中,根节点后面的 l l l 个数,是左子树的前序遍历,剩下的数是右子树的前序遍历;
    4. 有了左右子树的前序遍历和中序遍历,我们可以先递归创建出左右子树,然后再创建根节点;

    时间复杂度分析

    初始化时,用哈希表(unordered_map)记录每个值在中序遍历的位置,这样我们在递归到每个节点时,在中序遍历中查找根节点的位置的操作,只需要 O ( 1 ) O(1) O(1) 的时间。此时,创建每个节点需要的时间是 O ( 1 ) O(1) O(1) ,所以总时间复杂度是 O ( n ) O(n) O(n)

    变量说明

    • pos:记录每个节点在中序遍历序列中的位置。
    • pre: 题目输入数据,表示当前二叉树的前序遍历序列。
    • in: 题目输入数据,表示当前二叉树的中序遍历序列。
    • k: 表示当前根节点在所给中序遍历序列中的位置(分割左右子树)。
    • pl:表示当前根节点所代表的树在前序遍历序列中对应范围的起始位置。
    • pr:表示当前根节点所代表的树在前序遍历序列中对应范围的终点位置。
    • il:表示当前根节点所代表的树在中序遍历序列中对应范围的起始位置。
    • ir:表示当前根节点所代表的树在中序遍历序列中对应范围的终点位置。
    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        // 记录每个点在中序遍历序列中的位置
        unordered_map pos;
        
        TreeNode* buildTree(vector& preorder, vector& inorder) {
            int n = preorder.size();
            for (int i = 0; i < n; i ++ )
                 pos[inorder[i]] = i;
            return dfs(preorder, inorder, 0, n - 1, 0, n - 1);
        }
        
        // DFS递归遍历二叉树
        TreeNode* dfs(vector& pre, vector& in, int pl, int pr, int il, int ir) {
            if (pl > pr) return NULL;
            int k = pos[pre[pl]]; // 当前根节点在中序遍历序列中所在的位置
            TreeNode* root = new TreeNode(pre[pl]);
            root->left = dfs(pre, in, pl + 1, pl + k - il, il, k - 1);
            root->right = dfs(pre, in, pl + k + 1 -il, pr, k + 1, ir);
            return root;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    让人不顺眼的顺序表
    DQL数据查询语句之ORDER BY排序查询示例
    全面讲解GRASP原则
    Unity3d+GameFramework:资源分析,资源依赖,循环依赖检测
    seleniumwire获取百度指数
    CHINTERGEO2023中国测绘地理信息技术装备展览会,大势智慧在3010展台期待您的莅临!
    java 歌词解析 源代码, 在windows10下调试运行成功。
    微型微控制器托管双直流/直流升压转换器
    机器人入门(一)
    【JAVA并发】三、JAVA线程池详解
  • 原文地址:https://blog.csdn.net/qq_53064310/article/details/126079653