0105.从前序与中序遍历序列构造二叉树

1. 题目

2.解法

2.1 解法一(递归解法)

  • 时间复杂度O(n),n是树中的结点个数.
  • 空间复杂度O(n),返回答案需要的空间不算在内,需要O(n)哈希表的存储空间,另外还需要O(h)递归栈空间,由于h<n,所以总空间复杂度为O(n)
  • 代码
struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(): val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution{
private:
    unordered_map<int, int> index;  //哈希表

public:
    TreeNode* myBuildTree(vector<int> & preorder, vector<int> inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        if(preorder_left > preorder_right){   // 空树
            return nullptr;
        }

        // 前序遍历第一个结点就是根结点
        int preorder_root = preorder_left; // 数组下标

        // 在中序遍历中定位根结点
        int inorder_root = index[preorder[preorder_root]];  //数组下标

        // 建立根结点
        TreeNode* root = new TreeNode(preorder[preorder_root]);

        // 得到左子树的结点数目
        int size_left_subtree = inorder_root - inorder_left;

        //递归构造左子树,并连接到叶子结点
        // 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
        root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);


        // 递归地构造右子树,并连接到根节点
        // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
        root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);

        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        
        //构建哈希映射,快速定位根结点
        for(int i=0; i<n; i++){
            index[inorder[i]] = i;
        }

        return myBuildTree(preorder, inorder, 0, n-1, 0, n-1);
    }

};

2.2 解法二(非递归解法)

  • 时间复杂度O(n),n是树中的结点个数.
  • 空间复杂度O(n),返回答案需要的空间不算在内,需要O(n)哈希表的存储空间,另外还需要O(h)递归栈空间,由于h<n,所以总空间复杂度为O(n)
  • 图形化理解:从前序与中序遍历序列构造二叉树
  • 代码
class Solution{
public:
    TreeNode* buildTree(vector<int> & preorder, vector<int> inorder) {
        if(!preorder.size()){   // 空树
            return nullptr;
        }

        TreeNode* root = new TreeNode(preorder[0]);
        stack<TreeNode*> stk;

        stk.push(root);

        int inorderIndex = 0;

        for (int i=1; i<preorder.size(); ++i){
            int preorderVal = preorder[i];
            TreeNode* node = stk.top();

            if (node->val != inorder[inorderIndex]){
                node->left = new TreeNode(preorderVal);
                stk.push(node->left);
            }else{
                while(!stk.empty() && stk.top()->val == inorder[inorderIndex]){
                    TreeNode* node = stk.top();
                    stk.pop();
                    ++inorderIndex;
                }

                node->right = new TreeNode(preorderVal);
                stk.push(node->right);
            }
        }

        return root;
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值