根据两种顺序的遍历构造二叉树 3 题

19 阅读4分钟

889. 根据前序和后序遍历构造二叉树

image.png

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 前序:  根左右 
        # 后序:  左右根 

        ### 存在多解 , 规定 preorder[1] 为 左子树的根节点
        def myBuildTree(pre_left, pre_right, post_left, post_right):
            if pre_left > pre_right:
                return None 

            if pre_left == pre_right: # 只剩一个结点, 不存在 左子树
                return TreeNode(preorder[pre_left])

            # 规定 pre_left + 1 为 左子树根节点 位置   有一个前提: 左子树存在  !!!
            # 左子树根节点 在 postorder 的位置                   
            idx = dic[preorder[pre_left + 1]]
            left_size = idx - post_left + 1  # 0 1 2 

            root = TreeNode(preorder[pre_left])  # 根节点
            root.left = myBuildTree(pre_left + 1, pre_left + left_size, post_left, idx)
            root.right = myBuildTree(pre_left + left_size + 1, pre_right, idx + 1, post_right - 1)
            return root 

        dic = {x : i for i, x in enumerate(postorder)}
        n = len(preorder)
        return myBuildTree(0, n - 1, 0, n - 1)        

image.png

class Solution {
private:
    unordered_map<int, int> postDict;
public:
    TreeNode* myBuildTree(vector<int> &preorder, vector<int> &postorder, int pre_left, int pre_right, int post_left, int post_right){
        // 前序  根左右
        // 后序  左右根
        if (pre_left > pre_right){
            return nullptr;
        }
        if (pre_left == pre_right){
            return new TreeNode(preorder[pre_left]);
        }
        // 以下 讨论  存在 子树 的情形
        // 规定 pre[1]  为左子树的根节点
        int idx = postDict[preorder[pre_left + 1]];  // 左子树 根节点 在 postorder的索引
        int left_size = idx - post_left + 1;  // 左子树 节点数

        TreeNode* root = new TreeNode(preorder[pre_left]);
        root->left = myBuildTree(preorder, postorder, pre_left + 1, pre_left + left_size, post_left, idx);
        root->right = myBuildTree(preorder, postorder, pre_left + left_size + 1, pre_right, idx + 1, post_right - 1);
        return root;     

    }
    TreeNode *constructFromPrePost(vector<int> &preorder, vector<int> &postorder) {
        int n = preorder.size();
        for (int i = 0; i < n; i++) {
            postDict[postorder[i]] = i;
        }
        return myBuildTree(preorder, postorder, 0, n - 1, 0, n - 1);
    }
};

106. 从中序与后序遍历序列构造二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 中序: 左 根 右
        # 后序: 左 右 根  最后为 根  在 中序 中 区分 左右

        dic = {x : i for i, x in enumerate(inorder)} 

        def dfs(in_left, in_right, post_left, post_right):
            # 中序:  根 左 右
            # 后序: 左 右 根
            if post_left > post_right:
                return None

            idx = dic[postorder[post_right]]  # 根 的索引
            left_size = idx - in_left  # 左子树 大小 根 左右

            root = TreeNode(postorder[post_right])   
            root.left = dfs(in_left,  idx - 1, post_left, post_left + left_size - 1)
            root.right = dfs(idx + 1, in_right, post_left + left_size, post_right - 1)

            return root 


        n = len(inorder)
        return dfs(0, n - 1, 0, n - 1)

image.png

/**
 * Definition for a binary tree node.
 * 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> dic;
public:
    TreeNode* myBuildTree(vector<int>& inorder, vector<int>& postorder, int in_left, int in_right, int post_left, int post_right){
        // 前序  左根右
        // 后序: 左右根
        if (in_left > in_right){
            return nullptr;
        }

        int idx = dic[postorder[post_right]];  // 根节点  在 inorder 的索引
        int left_size = idx - in_left;  // 左子树 节点数

        TreeNode* root = new TreeNode(postorder[post_right]);
        root->left = myBuildTree(inorder, postorder, in_left, idx - 1, post_left, post_left + left_size - 1);
        root->right = myBuildTree(inorder, postorder, idx + 1, in_right, post_left + left_size, post_right - 1);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int n = postorder.size();
        for (int i = 0; i < n; ++i){
            dic[inorder[i]] = i;
        }
        return myBuildTree(inorder, postorder, 0, n - 1, 0, n - 1);
    }
};

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

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
      # 前序 根 左 右    第一个 根节点   在 中序 查找 根的位置  左右树 切分  继续递归
        # 中序 左 根 右  
        def dfs(pre_left, pre_right, in_left, in_right):# 处理的 preorder 的 元素索引范围,inorder 的元素索引范围
            if pre_left > pre_right:
                return None 

            # 分 左右子树
            idx = dic[preorder[pre_left]]  # 获取 中序中 根的 位置索引  # 
            left_size = idx - in_left  # 左子树 节点数  # 0  1 2 3 

            # 建根
            root = TreeNode(preorder[pre_left])
            root.left = dfs(pre_left + 1, pre_left + left_size, in_left, idx - 1)
            root.right = dfs(pre_left + left_size + 1, pre_right, idx + 1, in_right)
            return root 

        n = len(preorder)
        dic = {element : i for i, element in enumerate(inorder)} # 结点值 : 索引 
        return dfs(0, n - 1, 0, n - 1)

image.png

/**
 * Definition for a binary tree node.
 * 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> dic;
public:
    //  递归 构造模块
    TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int pre_left, int pre_right, int in_left, int in_right){
        
        if (pre_left > pre_right){
            return nullptr;
        }
        
        int idx = dic[preorder[pre_left]];  // 本次循环 建树的根节点 在 inorder 的位置
        int left_size = idx - in_left;  // 左子树的节点个数

        // 建 根节点
        TreeNode* root = new TreeNode(preorder[pre_left]);
        root->left = myBuildTree(preorder, inorder, pre_left + 1, pre_left + left_size, in_left, idx - 1);
        root->right = myBuildTree(preorder, inorder, pre_left + left_size + 1, pre_right, idx + 1, in_right);

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        // 构造 哈希映射 快速定位 inorder 中的根节点
        int n = preorder.size();
        for (int i = 0; i < n; ++i){
            dic[inorder[i]] = i;   // 节点值 : inorder 中的索引
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1); // 要处理的 preorder 中的 节点索引范围, inorder 中的节点 索引范围
    }
};

用于 理解 的解法

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
    # 前序 根 左 右    第一个 根节点   在 中序 查找 根的位置  左右树 切分  继续递归
    # 中序 左 根 右   

    ## 
        if not preorder: 
            return None 
        idx = inorder.index(preorder[0])   # 中序中 左右子树的分割点 根的索引  同时也是 左子树的节点数
        left = self.buildTree(preorder[1 : 1 + idx], inorder[: idx])
        right = self.buildTree(preorder[1 + idx : ], inorder[idx + 1: ])
        return TreeNode(preorder[0], left, right)

image.png