剑指 Offer 07 重建二叉树
概述
https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/
https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
动态规划法
前序遍历的结果中,元素的排列顺序为:root,left subtree,right subtree;
中序遍历的结果中,元素的排列顺序为:left subtree,root,right subtree;
当我们构造二叉树时,首先确定根节点,之后递归确定左右子树。
为此,我们需要:
- 确定根节点:即前序遍历结果中的第一项;
- 确定左右子树的元素范围:根据上一点中确定得到的 root,找出其在中序遍历结果中的索引,减去其起始索引,即可得到左子树的元素个数,进而得到右子树的元素个数。
至于如何确定 root 元素的索引,我这里是先构造了一个 map。
时间复杂度 O(n)。
class Solution {
public:
    map<int, int> inorderMap;
    TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        auto size = inorder.size();
        for (int i = 0; i < size; i++) {
            inorderMap[inorder[i]] = i;
        }
        return helper(preorder, inorder, 0, size - 1, 0, size - 1);
    }
    TreeNode *helper(vector<int> &preorder, vector<int> &inorder, int preLeft, int preRight, int inLeft, int inRight) {
        if (preLeft > preRight) {
            return nullptr;
        }
        auto root = new TreeNode(preorder[preLeft]);
        int inIdx = inorderMap[preorder[preLeft]];
        int numLeft = inIdx - inLeft;
        root->left = helper(preorder, inorder, preLeft + 1, preLeft + numLeft, inLeft, inIdx - 1);
        root->right = helper(preorder, inorder, preLeft + numLeft + 1, preRight, inIdx + 1, inRight);
        return root;
    }
};
Links: sword-offer-07