刷题(二):重建二叉树

96 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

题目:

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

 

示例 1:

image.png

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]

Output: [3,9,20,null,null,15,7]

示例 2:

Input: preorder = [-1], inorder = [-1]

Output: [-1]  

限制:

0 <= 节点个数 <= 5000

思路分析:

首先,我们要先知道前序遍历和中序遍历的遍历顺序。

       二叉树前序遍历的顺序为:

       1.先遍历根节点;

       2.随后递归地遍历左子树;

       3.最后递归地遍历右子树。

       二叉树中序遍历的顺序为:

       1.先递归地遍历左子树;

       2.随后遍历根节点;

       3.最后递归地遍历右子树。

方法:递归

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

具体步骤如下:

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

时间复杂度分析

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

AC代码:

class Solution {
public:
    vector<int> preorder, inorder;
    map<int, int> mp;
    TreeNode* buildTree(vector<int>& _preorder, vector<int>& _inorder) {
        preorder = _preorder, inorder = _inorder;
        for(int i = 0; i < inorder.size(); i ++ ){
            mp[inorder[i]] = i;
        }
        return dfs(0, preorder.size() - 1, 0, inorder.size() - 1);
    }

    TreeNode* dfs(int pl, int pr, int il, int ir){
        if(pl > pr) return NULL;
        TreeNode* root = new TreeNode(preorder[pl]);
        int p = mp[preorder[pl]];
        root->left = dfs(pl + 1, pl + 1 + p - il - 1, il, p - 1);
        root->right = dfs(pl + 1 + p - il - 1 + 1, pr, p + 1, ir);
        return root;
    }
};

image.png

来源:力扣(LeetCode)

链接:leetcode.cn/problems/zh…