剑指 Offer 07. 重建二叉树 ✨✨

225 阅读1分钟

通过以上三步,可确定 三个节点 :1.树的根节点、2.左子树根节点、3.右子树根节点。 对于树的左、右子树,仍可使用以上步骤划分子树的左右子树。

分治算法解析:

递推参数: 当前树的根节点 root 、当前树的左边界 left 、当前树的右边界 right ;

终止条件: 当 left > right ,代表已经越过叶节点,此时返回 null ;

递推工作

  1. 建立根节点 node : 节点值为 preorder[root] ;
  2. 划分左右子树: 查找根节点在中序遍历 inorder 中的索引 i ;
  3. 构建左右子树: 开启左右子树递归;
/**
 * 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:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        this->preorder = preorder;
        for(int i = 0; i < inorder.size(); i++){
            //利用哈希表 查找根节点在中序遍历 inorder 中的索引 i 
            dic[inorder[i]] = i;
        }
        return recur(0, 0, inorder.size() - 1);
    }
private:
    vector<int> preorder;
    unordered_map<int,int> dic;
    TreeNode* recur(int root, int left, int right){
        //递归终止条件
        if (left > right) return nullptr; 

        TreeNode *node = new TreeNode(preorder[root]);
        //根节点在中序遍历序列中的位置
        int i = dic[preorder[root]];

        node->left = recur(root+1, left, i-1); //左子树递归
        //右子树根节点索引:根节点索引 + 左子树长度 + 1
        node->right = recur(root+i-left+1, i+1, right); 
        return node;
    }
};