题解 | #重建二叉树#

重建二叉树

http://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6

解题思路:在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但是在树的中序遍历中,根节点的值在序列的中间,左子树的节点的值位于根节点的值的左边,而右子树的节点的值位于根节点的值的右边。因此根据先序遍历第一个值为根节点的值,扫描中序遍历,找到根节点的值的位置,位于根节点位置的左边的是左子树的节点,位于根节点位置右边的是右子树的节点。在扫描完之后,我们分别找到了左右子树先序和中序的遍历,我们就可以用同样的方法分别构建左子树和右子树,接下来的事情可以用递归来实现。

时间复杂度:O(n),在遍历的过程都是O(n)的数量级;

空间复杂度:O(n),递归使用的栈的最大深度不超过n;

基于C++实现:

class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        //当前序或者中序遍历为空的情况
        if(pre.empty() || vin.empty()){
            return nullptr;
        }
        //建立根节点
        int root = pre[0];
        TreeNode *tree = new TreeNode(root);
        int length = pre.size();
        //如果长度为1,直接返回根节点
        if(length == 1){
            return tree;
        }
        auto posi = find(vin.begin(), vin.end(), root);
        //如果在中序中没有检测到根节点
        if(posi == vin.end()){
            return nullptr;
        }
        //计算左右子树的长度
        int num_left = posi - vin.begin();
        int num_right = vin.end() - posi - 1;
        vector<int> left_pre;
        vector<int> left_vin;
        vector<int> right_pre;
        vector<int> right_vin;
        //找左右子树对应的先序和中序遍历
        left_pre.assign(pre.begin()+1, pre.begin()+1+num_left);
        right_pre.assign(pre.end()-num_right, pre.end());
        left_vin.assign(vin.begin(), vin.begin()+num_left);
        right_vin.assign(vin.end()-num_right, vin.end());
        //递归的建立左右子树
        tree->left = reConstructBinaryTree(left_pre, left_vin);
        tree->right = reConstructBinaryTree(right_pre, right_vin);
        return tree;
    }
};
全部评论

相关推荐

美团 后端开发 总包n(15%是股票)
点赞 评论 收藏
分享
评论
9
收藏
分享
牛客网
牛客企业服务