【二叉树专题】剑指 Offer 07. 重建二叉树

本问题对应课程链接:剑指offer刷题第六期

要求:

1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。
2、给出你代码所用的时间复杂度和空间复杂度

共以下 27 个回答

  • YOLO 普通 2024年3月29日 下午9:23
     /*输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。 */
    class Solution {
        Map<Integer,Integer> map = new HashMap();   // 定义哈希
        public TreeNode deduceTree(int[] preorder, int[] inorder) {
            if(preorder == null || preorder.length <= 0){
                return null;
            }
            //中序遍历数组映射,求某个元素下标
            for(int i = 0; i < inorder.length ; i++){
                map.put(inorder[i],i);
            }
    
            TreeNode root = f(preorder, 0 , preorder.length-1 , inorder , 0 ,inorder.length-1);
            return root;
    
        }
    
        TreeNode f(int[] preorder,int l1,int r1,int[] inorder,int l2,int r2){
            //前序遍历或者中序遍历为空时,表示这棵树不存在
            if(l1 > r1 && l2 > r2){
                return null;
            }
            //传入前序遍历的根节点
            TreeNode root = new TreeNode(preorder[l1]);
            int i = map.get(preorder[l1]);  //根节点在中序遍历中的下标
    
            root.left = f(preorder,l1+1,l1+(i-l2),inorder,l2,i-1);
            root.right = f(preorder,l1+(i-l2)+1,r1,inorder,i+1,r2);
            return root;
        }
    }
    
    0 赞同 0 条回复
  • kfaebot 普通 2024年3月21日 下午4:18
    /**
     * 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 {
    public:
        TreeNode* build(vector<int>& preorder, int prebegin, int preend, vector<int>& inorder,int inbegin,int inend){
            if(prebegin==preend){
                return nullptr;
            }
    
            //根据前序遍历的第一个找到中间根节点
            int rootval=preorder[prebegin];
            TreeNode* root=new TreeNode(rootval);
    
            //叶子节点
            if(preend-prebegin==1){
                return root;
            }
    
            //在中序遍历中找到分割点
            int tmp;
            for(int i=inbegin;i<inend;i++){
                if(inorder[i]==rootval){
                    tmp=i;
                    break;
                }
            }
    
            //前序遍历序列的左右子树区间,左闭右开
            //左子树区间
            int left_prebegin=prebegin+1;
            int left_preend=prebegin+1+tmp-inbegin;
            //右子树区间
            int right_prebegin=prebegin+1+tmp-inbegin;
            int right_preend=preend;
    
            //中序遍历序列的左右子树区间,左闭右开
            //左子树区间
            int left_inbegin=inbegin;
            int left_inend=tmp;
            //右子树区间
            int right_inbegin=tmp+1;
            int right_inend=inend;
    
            //遍历
            root->left=build(preorder, left_prebegin, left_preend, inorder, left_inbegin, left_inend);
            root->right=build(preorder, right_prebegin, right_preend, inorder, right_inbegin, right_inend);
    
            return root;
        }
        TreeNode* deduceTree(vector<int>& preorder, vector<int>& inorder) {
            if(preorder.size()==0||inorder.size()==0){
                return nullptr;
            }
            return build(preorder,0,preorder.size(),inorder,0,inorder.size());
        }
    };
    
    0 赞同 0 条回复
  • NULL 普通 2024年3月20日 下午9:39

    Map< Integer, Integer > map = new HashMap();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
    if(preorder null || preorder.length <= 0){
    return null;
    }
    // 简历中序遍历数组的映射(就是为了快速求出某个元素的下标)
    for(int i = 0; i < inorder.length; i++) {
    map.put(inorder[i], i);
    }

        TreeNode root = f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    
        return root;
    }
    
    TreeNode f(int[] preorder, int l1, int r1, int[] inorder, int l2, int r2) {
        // 前序遍历或者中序遍历为空时,表示这棵树不存在,直接返回 null
        if( l1 > r1 || l2 > r2){
            return null;
        }
        // 根节点
        TreeNode root = new TreeNode(preorder[l1]);
        // 根节点在中序遍历中的下标
        int i = map.get(preorder[l1]);
        // 递归求解
        root.left = f(preorder, l1 + 1, l1 + (i - l2), inorder, l2, i - 1);
        root.right = f(preorder, l1 + (i - l2) + 1, r1, inorder, i + 1, r2);
    
        return root;
    }
    
    0 赞同 0 条回复
  • 紫芝 普通 2024年3月15日 下午10:12

    思路:前序遍历第一个值即为父节点,然后在中序遍历中找到父节点,其左边的值为左子树,右边的值为右子树,然后递归的建立二叉树。

    “`c++
    class Solution {
    public:
    TreeNode* GeneTree(vector& preorder, int prel, int prer, vector& inorder, int inl, int inr) {
    if (prel > prer) return nullptr;
    TreeNode* root = new TreeNode(preorder[prel]);
    int mid = inl;
    while (mid <= inr && inorder[mid] != preorder[prel]) mid++; root->left = GeneTree(preorder, prel+1, prel+mid-inl, inorder, inl, mid-1);
    root->right = GeneTree(preorder, prel+mid-inl+1, prer, inorder, mid+1, inr);
    return root;
    }
    TreeNode* deduceTree(vector
    & preorder, vector& inorder) {
    return GeneTree(preorder, 0, preorder.size()-1, inorder, 0, inorder.size()-1);
    }
    };
    “`

    0 赞同 0 条回复
  • 叫不醒装睡的人 普通 2024年3月15日 下午6:32
    class Solution {
        // 先序遍历是 根左右
        // 中序遍历是 左根右
        // Map 中存放中序遍历下标与值的映射关系
        // 当获取到 idx 时,可以划分左右子树
        // left 表示当前子树在中序遍历结果数组中的左边界索引,right 表示当前子树在中序遍历结果数组中的右边界索引
        int[] preorder;
        HashMap<Integer, Integer> hmap = new HashMap<>();
    
        public TreeNode deduceTree(int[] preorder, int[] inorder) {
            this.preorder = preorder;
            for (int i = 0; i < inorder.length; i++) {
                hmap.put(inorder[i], i);
            }
            return recur(0, 0, inorder.length - 1);
        }
    
        private TreeNode recur(int root, int left, int right) {
            // 递归终止
            if (left > right) {
                return null;
            }
            // 建立根节点,第一次走到这里时先序遍历的第一个元素肯定是根结点
            TreeNode node = new TreeNode(preorder[root]);
            // 根据这个根结点的值来确定中序遍历中该元素的下标
            // 划分根节点、左子树、右子树
            int idx = hmap.get(preorder[root]);
            // 开启左子树递归
            node.left = recur(root + 1, left, idx - 1);
            // 开启右子树递归
            node.right = recur(root + i - left + 1, idx + 1, right);
            // 回溯返回根节点
            return node;
        }
        // 时间复杂度为 O(n)
        // 空间复杂度为 O(n)
    }
    
    
    0 赞同 0 条回复
  • Let it be 永久会员 2024年3月14日 下午5:49

    class Solution {

    public TreeNode deduceTree(int[] preorder, int[] inorder) {
        return build(preorder, inorder,0, preorder.length-1, 0, inorder.length-1);
    }
    
    public TreeNode build(int[] preorder, int[] inorder, int preL, int preR, int inL, int inR){
        if(preL>preR || inL > inR)return null;边界
        int val = preorder[preL];
        TreeNode root = new TreeNode(val);
        int index = 0 ;
        for(int i=inL ;i <= inR; i++){
            if(inorder[i] == val){
                index = i;
                break;
            }
        }
        int leftSize = index -inL; 
        root.left = build(preorder, inorder, preL+1, preL+leftSize, inL, index-1);
        root.right = build(preorder, inorder, preL+leftSize+1, preR, index+1, inR);
        return root;
    }
    

    }

    0 赞同 0 条回复
  •  南木 普通 2024年3月13日 下午4:33

    忘了还有哈希表建立索引,
    时间复杂度 O(N) : 其中 NN 为树的节点数量。初始化 HashMap 需遍历 inorder ,占用 O(N) 。递归共建立 NN 个节点,每层递归中的节点建立、搜索操作占用 O(1) ,因此使用 O(N) 时间。
    空间复杂度 O(N) : HashMap 使用 O(N) 额外空间;最差情况下(输入二叉树为链表时),递归深度达到 N ,占用 O(N)的栈帧空间;因此总共使用 O(N) 空间。

        Map< Integer, Integer > map = new HashMap();
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            if(preorder == null || preorder.length <= 0){
                return null;
            }
            // 简历中序遍历数组的映射(就是为了快速求出某个元素的下标)
            for(int i = 0; i < inorder.length; i++) {
                map.put(inorder[i], i);
            }
    
            TreeNode root = f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    
            return root;
        }
    
        TreeNode f(int[] preorder, int l1, int r1, int[] inorder, int l2, int r2) {
            // 前序遍历或者中序遍历为空时,表示这棵树不存在,直接返回 null
            if( l1 > r1 || l2 > r2){
                return null;
            }
            // 根节点
            TreeNode root = new TreeNode(preorder[l1]);
            // 根节点在中序遍历中的下标
            int i = map.get(preorder[l1]);
            // 递归求解
            root.left = f(preorder, l1 + 1, l1 + (i - l2), inorder, l2, i - 1);
            root.right = f(preorder, l1 + (i - l2) + 1, r1, inorder, i + 1, r2);
    
            return root;
        }
    
    0 赞同 0 条回复
  • 东 普通 2024年3月12日 下午9:05

    ~~~java
    class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
    //用hashmap记录inorder可以减少递归中的循环带来的消耗
    HashMap<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < inorder.length; i++) {
    map.put(inorder[i], i);
    }

        return buildTreeHelper(preorder, 0, preorder.length, inorder, 0, inorder.length,map);
    }
    
    private TreeNode buildTreeHelper(int[] preorder, int p_start, int p_end, int[] inorder, int i_start, int i_end,HashMap<Integer, Integer> map) {
        // preorder 为空,直接返回 null
        if (p_start == p_end) {
            return null;
        }
        //记录当前根结点
        int root_val = preorder[p_start];
        TreeNode root = new TreeNode(root_val);
        //在中序遍历数组中找到根节点的位置
        int i_root_index = map.get(root_val);
        //记录左子树的个数
        int leftNum = i_root_index - i_start;
        //递归的构造左子树
        root.left = buildTreeHelper(preorder, p_start + 1, p_start  + 1 + leftNum, inorder, i_start, i_root_index,map);
        //递归的构造右子树
        root.right = buildTreeHelper(preorder, p_start + leftNum + 1, p_end, inorder, i_root_index + 1, i_end,map);
        return root;
    }
    

    }
    java

    0 赞同 0 条回复
  • 白雪公主倒拔垂杨柳 永久会员 2024年3月12日 下午8:45
    class Solution {
        Map<Integer, Integer> map = new HashMap();
        public TreeNode deduceTree(int[] preorder, int[] inorder) {
    
            for(int i=0;i<inorder.length;i++){
                map.put(inorder[i],i);
            }
            return f(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    
        }
    
        TreeNode f(int[] pre, int l1, int r1, int[] in, int l2, int r2){
            if(l1>r1 || l2>r2){
                return null;
            }
    
            TreeNode root = new TreeNode(pre[l1]);
            int i = map.get(pre[l1]);
    
            root.left = f(pre,l1+1,l1+(i-l2),in,l2,i-1);
            root.right=f(pre,l1+(i-l2)+1,r1,in,i+1,r2);
    
            return root;
        }
    

    时间复杂度 O(N) : 其中 NN 为树的节点数量。初始化 HashMap 需遍历 inorder ,占用 O(N) 。递归共建立 NN 个节点,每层递归中的节点建立、搜索操作占用 O(1) ,因此使用 O(N) 时间。
    空间复杂度 O(N) : HashMap 使用 O(N) 额外空间;最差情况下(输入二叉树为链表时),递归深度达到 N ,占用 O(N)的栈帧空间;因此总共使用 O(N) 空间。

    0 赞同 0 条回复
  • RunAsOne 普通 2024年3月12日 下午3:58

    Day9 有点难度。。

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, val=0, left=None, right=None):
    #         self.val = val
    #         self.left = left
    #         self.right = right
    class Solution(object):
    
        def deduceTree(self, preorder, inorder):
            """
            :type preorder: List[int]
            :type inorder: List[int]
            :rtype: Optional[TreeNode]
            """
            map = {}
            for i in range(len(inorder)):
                map[inorder[i]] = i
    
            def cur(preorder, l1, r1, inorder, l2, r2):
                if l1>r1 or l2>r2:
                    return None
                root = TreeNode(preorder[l1])
                i = map[preorder[l1]]
                root.left = cur(preorder, l1+1, l1+i-l2, inorder, l2, i-1)
                root.right = cur(preorder, l1+i-l2+1, r1, inorder, i+1, r2)
                return root
    
            return cur(preorder, 0, len(preorder)-1, inorder, 0, len(inorder) - 1)
    
    
    0 赞同 0 条回复
  • 南梁陈庆之 普通 2024年3月12日 上午12:39

    分治思想重置二叉树

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode() {}
     *     TreeNode(int val) { this.val = val; }
     *     TreeNode(int val, TreeNode left, TreeNode right) {
     *         this.val = val;
     *         this.left = left;
     *         this.right = right;
     *     }
     * }
     */
    class Solution {
        int[] preorder ;
        Map<Integer,Integer> map = new HashMap<>();
        public TreeNode deduceTree(int[] preorder, int[] inorder) {
            this.preorder = preorder;
            for (int i = 0; i < inorder.length; i++) {
                map.put(inorder[i], i);
            }
            return recur(0, 0, inorder.length - 1);
        }
        TreeNode recur(int root, int left ,int right) {
            if (left > right) {
                return null;
            }
            TreeNode node = new TreeNode(preorder[root]);
            int i = map.get(preorder[root]);
            node.left = recur(root + 1, left , i - 1);
            node.right = recur(root + 1 + i - left, i + 1 , right);
            return node;
        }
    }
    
    0 赞同 0 条回复
  • 神经蛙 普通 2024年3月12日 上午12:06

    class Solution {
    private:
    unordered_map<int,int> myMap;
    public:
    TreeNode* deduceTree(vector& preorder, vector& inorder) {

        for(int i=0;i<inorder.size();i++){
            myMap[inorder[i]] = i;
        }
        TreeNode *root = f(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
        return root;
    }
    TreeNode* f(vector<int>& preorder,int l1,int r1,vector<int>& inorder,int l2,int r2){
        if(l1 > r1 || l2 > r2){
            return nullptr;
        }
    
        TreeNode *root = new TreeNode(preorder[l1]);
        int i = myMap[preorder[l1]];
    
        root->left = f(preorder,l1+1,l1+(i-l2),inorder,l2,i-1);
        root->right = f(preorder,l1+(i-l2)+1,r1,inorder,i+1,r2);
    
        return root;
    
    }
    

    };
    递归,难点是计算左右子树的开始和结束位置

    0 赞同 0 条回复
  • MARS 普通 2024年3月11日 下午11:25

    day9第一题

    function deduceTree(preorder: number[], inorder: number[]): TreeNode | null {
        if (preorder.length == 0 || inorder.length == 0) return null
        //先序第一个为头节点,中序头节点在中间
        let nodeVal = preorder.shift()
        let node = new TreeNode(nodeVal)
        if (inorder.length == 1) return node //中序长度为1,则返回
        let index = inorder.indexOf(nodeVal)
        node.left = deduceTree(preorder.slice(0, index), inorder.slice(0, index))  //先序已经弹出一个
        node.right = deduceTree(preorder.slice(index), inorder.slice(index + 1)) //中序没有弹出,且在index位置
    
        return node
    };
    
    0 赞同 0 条回复
  • 言之命至 普通 2024年3月11日 下午9:38
        Map< Integer, Integer > map = new HashMap(); //先定义一个全局的哈希表映射
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            if(preorder == null || preorder.length <= 0){
                return null;
            }
            // 遍历中序遍历数组的映射(就是为了快速求出某个元素的下标)
            for(int i = 0; i < inorder.length; i++) {
                map.put(inorder[i], i);
            }
    
            TreeNode root = f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    
            return root;
        }
    
        TreeNode f(int[] preorder, int l1, int r1, int[] inorder, int l2, int r2) {
            // 前序遍历或者中序遍历为空时,表示这棵树不存在,直接返回 null
            if( l1 > r1 || l2 > r2){
                return null;
            }
            // 根节点
            TreeNode root = new TreeNode(preorder[l1]);
            // 根节点在中序遍历中的下标
            int i = map.get(preorder[l1]);
            // 递归求解
            root.left = f(preorder, l1 + 1, l1 + (i - l2), inorder, l2, i - 1);
            root.right = f(preorder, l1 + (i - l2) + 1, r1, inorder, i + 1, r2);
    
            return root;
        }
    

    时间复杂度 O(N) ,空间复杂度 O(N)

    0 赞同 0 条回复
  • helloMoon 普通 2024年3月11日 下午9:20

    重建二叉树java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode() {}
     *     TreeNode(int val) { this.val = val; }
     *     TreeNode(int val, TreeNode left, TreeNode right) {
     *         this.val = val;
     *         this.left = left;
     *         this.right = right;
     *     }
     * }
     */
    class Solution {
    
        Map<Integer, Integer> map = new HashMap();
        public TreeNode deduceTree(int[] preorder, int[] inorder) {
            if(preorder == null || preorder.length <= 0){
                return null;
            }
    
            for(int i = 0; i < inorder.length; i ++ ){
                map.put(inorder[i], i);
            }
    
            TreeNode root  = f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length -1);
    
            return root;
        }
    
        TreeNode f(int[] preorder, int l1, int r1, int[] inorder, int l2, int r2){
            if(l1 > r1 || l2 > r2){
                return null;
            }
    
            TreeNode root = new TreeNode(preorder[l1]);
    
            int i = map.get(preorder[l1]);
    
            root.left = f(preorder, l1 + 1, l1 + (i - l2), inorder, l2, i - 1);
            root.right = f(preorder, l1 + (i - l2) + 1, r1, inorder, i + 1, r2);
    
            return root;
        }
    }
    
    0 赞同 0 条回复
  • Free 普通 2024年3月11日 下午8:46
    /**
     * 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 
    {
    public:
        TreeNode* deduceTree(vector<int>& preorder, vector<int>& inorder) 
        {
            int previ = 0;
            return bulid(preorder, inorder, previ, 0, preorder.size() - 1);
        }
    
        TreeNode* bulid(vector<int>& preorder, vector<int>& inorder, int& previ, int left, int right)
        {
            if(left > right)
                return nullptr;
            int rooti = right;
            while(rooti >= left)
            {
                if(preorder[previ] == inorder[rooti])
                    break;
                rooti--;
            }
            previ++;
            TreeNode* root = new TreeNode(inorder[rooti]);
            root->left = bulid(preorder, inorder, previ, left, rooti - 1);
            root->right = bulid(preorder, inorder, previ, rooti + 1, right);
            return root;
        }
    };
    

    时空复杂度O(N)

    0 赞同 0 条回复
  • Jimmy 普通 2024年3月11日 下午8:34

    使用递归的方法实现

    /**
     * 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> myMap;
    public:
        TreeNode* deduceTree(vector<int>& preorder, vector<int>& inorder) {
    
            for(int i=0;i<inorder.size();i++){
                myMap[inorder[i]] = i;
            }
            TreeNode *root = f(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
            return root;
        }
        TreeNode* f(vector<int>& preorder,int l1,int r1,vector<int>& inorder,int l2,int r2){
            if(l1 > r1 || l2 > r2){
                return nullptr;
            }
    
            TreeNode *root = new TreeNode(preorder[l1]);
            int i = myMap[preorder[l1]];
    
            root->left = f(preorder,l1+1,l1+(i-l2),inorder,l2,i-1);
            root->right = f(preorder,l1+(i-l2)+1,r1,inorder,i+1,r2);
    
            return root;
    
        }
    };
    
    0 赞同 0 条回复
  • 方铎码农 普通 2024年3月11日 下午3:52

    类似归并排序的分治递归方法
    时间复杂度$O(n)$,空间复杂度$O(n)$

    class Solution {
        private Map<Integer,Integer> indexMap;
    
        private TreeNode myTreeBuilding(int[] preorder, int[] inorder, int prel ,int prer, int inl, int inr){
            if(prel > prer) return null;
            int pre_root = prel;
            int in_root = indexMap.get(preorder[pre_root]);
            TreeNode root = new TreeNode(preorder[pre_root]);
            int sizeOfLeft = in_root - inl;
            root.left = myTreeBuilding(preorder,inorder,prel+1,prel+sizeOfLeft, inl, in_root-1);
            root.right = myTreeBuilding(preorder,inorder, prel+sizeOfLeft+1, prer, in_root+1 , inr);
            return root;
        }
    
    
        public TreeNode deduceTree(int[] preorder, int[] inorder) {
            int n = preorder.length;
            indexMap = new HashMap<Integer,Integer>();
            for(int i = 0; i < n; i++){
                indexMap.put(inorder[i],i);
            }
            return myTreeBuilding(preorder,inorder,0,n-1,0,n-1);
        }
    }
    
    0 赞同 0 条回复
  • mpweixin用户 普通 2024年3月11日 下午3:31

    HashMap<Integer, Integer> map = new HashMap<>();//标记中序遍历
    int[] preorder;//保留的先序遍历,方便递归时依据索引查看先序遍历的值
    public TreeNode deduceTree(int[] preorder, int[] inorder) {
    this.preorder =preorder;
    for(int i=0;i<inorder.length;i++){
    hmap.put(inorder[i],i);
    }
    return recur(0,0,inorder.length-1);
    }
    TreeNode recur(int root,int left,int right){
    if(left>right) return null;
    TreeNode node =new TreeNode(preorder[root]);
    int i=hmap.get(preorder[root]);
    node.left =recur(root+1,left,i-1);
    node.right=recur(root+i-left+1,i+1,right);
    return node;
    }
    需要再理解

    0 赞同 0 条回复
  • 0 赞同 0 条回复
  • Thaddeus 永久会员 2024年3月11日 上午8:46

    打卡

    class Solution {
    public:
        TreeNode* mydeduceTree(vector<int>& pre, int l1, int r1, vector<int>& in, int l2, int r2) {
            if(l1 > r1 || l2 > r2) return nullptr;
            int idx = hash[pre[l1]];
            TreeNode* newNode = new TreeNode(pre[l1]);
            newNode->left = mydeduceTree(pre, l1 + 1, l1 + idx -l2, in, l2, idx - 1);
            newNode->right = mydeduceTree(pre, l1 + idx - l2 + 1, r1, in, idx + 1, r2);
            return newNode;
    
        }
        TreeNode* deduceTree(vector<int>& preorder, vector<int>& inorder) {
            for(int i = 0; i < inorder.size(); ++i) hash[inorder[i]] = i;
            return mydeduceTree(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1);
    
        }
    private:
        unordered_map<int, int> hash;
    };
    
    0 赞同 0 条回复
  • Yox 普通 2024年3月11日 上午8:26

    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 deduceTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
    hmap,preorder = {}, preorder
    for i in range(len(inorder)):
    hmap[inorder[i]] = i

        def recur(root,left,right):
            if left > right:return
            node = TreeNode(preorder[root])
            i = hmap[preorder[root]] #根据pre里面的root节点位置找inorder的顺序划分左右子树
            node.left = recur(root+1,left,i-1)
            node.right = recur(root+i-left+1,i+1,right)
            return node
        return recur(0,0,len(inorder)-1)
    

    双on 第一个参数的root是preorder的位置,永远根据preorder找根节点。left和right是在inorder的位置。

    0 赞同 0 条回复
  • Raphtalia. 普通 2024年3月11日 上午12:59

    /**
    * struct TreeNode {
    * int val;
    * struct TreeNode *left;
    * struct TreeNode *right;
    * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    * };
    */
    #include
    #include
    class Solution {
    public:
    /**
    * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    *
    *
    * @param preOrder int整型vector
    * @param vinOrder int整型vector
    * @return TreeNode类
    */

    TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {
        // write code here
        this->preOrder = preOrder;//给前序赋值
        for(int i = 0; i < vinOrder.size(); i ++){
            map[vinOrder[i]] = i;
        }//标记根节点在中序中的位置
        return recur(0, 0, vinOrder.size() - 1);
    }
    

    private:
    vector preOrder;
    unordered_map<int, int> map;
    TreeNode* recur(int root, int left, int right){
    if(left > right) return nullptr;//边界条件
    TreeNode* node = new TreeNode(preOrder[root]);//构建头节点
    int bound = map[preOrder[root]];//找到分界点
    node->left = recur(root + 1, left, bound – 1);
    node->right = recur(root + bound -left + 1, bound + 1, right);
    return node;
    }
    };

    0 赞同 0 条回复
  • 云无深雁影 普通 2024年3月11日 上午12:49

    class Solution {
    private HashMap<Integer,Integer> inorderPosition;
    public TreeNode deduceTree(int[] preorder, int[] inorder) {
    inorderPosition = new HashMap<>();
    for(int i = 0; i < inorder.length; i++){
    inorderPosition.put(inorder[i],i);
    }
    return rec(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }
    private TreeNode rec(int[] preorder, int l1, int r1, int[] inorder, int l2, int r2){
    if(l1 > r1 || l2 > r2)
    return null;
    TreeNode root = new TreeNode(preorder[l1]);
    int i = inorderPosition.get(preorder[l1]);
    root.left = rec(preorder,l1+1,l1+i-l2,inorder,l2,i-1);
    root.right = rec(preorder,r1-r2+i+1,r1,inorder,i+1,r2);
    return root;
    }
    }
    //使用递归算法 时间复杂度On 空间复杂度On

    0 赞同 0 条回复
  • 机电皮怪 永久会员 2024年3月10日 下午11:22

    思路是看了题解才会的,用哈希表储存节点编号和中序遍历的关系然后递归中用先序找出头节点的编号
    时间复杂度O(n)
    空间复杂度O(n)

    “`C++
    class Solution {
    public:
    TreeNode* deduceTree(vector& preorder, vector& inorder) {
    if(preorder.empty() == true || inorder.empty() == true)
    {
    return nullptr;
    }
    this->preorder = preorder;
    for(int i = 0; i < inorder.size(); i++) { submap[inorder[i]] = i; } return build(0, 0, inorder.size() - 1); } private: vector
    preorder;
    unordered_map<int,int> submap;
    //第一个参数用于利用前序遍历来确定节点在中序遍历中的位置
    //第二、三个参数用于判断递归是否满足结束条件
    TreeNode* build(int root, int left, int right)
    {
    //递归终止条件
    if (left > right)
    {
    return nullptr;
    }
    //建立根节点
    TreeNode* node = new TreeNode(preorder[root]);
    //划分左、中、右子树,i为中序遍历的中间节点
    int i = submap[preorder[root]];
    //递归左子树
    node->left = build(root + 1, left, i – 1);
    //递归右子树
    node->right = build(root + i – left + 1, i + 1, right);

        return node;
    }
    

    };

    “`

    0 赞同 0 条回复
  • heathhou 普通 2024年3月10日 下午9:39
    class Solution {
    public:
        unordered_map<int, int> map;
        TreeNode* deduceTree(vector<int>& preorder, vector<int>& inorder) {
            if(preorder.empty()){
                return nullptr;
            }
    
    
            for(int i = 0; i < inorder.size(); ++i){
                map[inorder[i]] = i;
            }
    
            TreeNode* root = f(preorder, 0, preorder.size() - 1, inorder , 0, inorder.size() - 1);
    
            return root;
    
        }
    
        // 递归函数:根据先序遍历和中序遍历构建二叉树
        TreeNode* f(vector<int>& preorder, int l1, int r1, vector<int> inorder, int l2, int r2){
            // 递归函数的终止条件
            if(l1 > r1 || l2 > r2){
                return nullptr;
            }
    
            TreeNode* root = new TreeNode(preorder[l1]);
            int i = map[preorder[l1]];
            root->left = f(preorder, l1 + 1, l1 + i - l2, inorder, l2, i -1);
            root->right = f(preorder, l1 + i - l2 + 1, r1, inorder, i + 1, r2);
    
            return root;
    
        }
    };
    
    0 赞同 0 条回复
  • 王位詮釋 普通 2024年3月10日 下午9:18
    class Solution {
        public TreeNode deduceTree(int[] preorder, int[] inorder) {
            boolean[] visited = new boolean[preorder.length];
            TreeNode root = build(preorder,inorder,visited,0,preorder.length-1);
            return root;
        }
        public TreeNode build(int[] preorder,int[] inorder,boolean[] visited,int begin,int end){
            //begin代表重构中序遍历数组时候的初始索引,end代表结束索引
            //如果begin>end的话表示这一部分已经重构完了
            //visited数组表示已经遍历过的根节点(索引与先序遍历数组对应)
            if(begin>end){//边界条件 
                return null;
            }
            int rootIndex = 0;
            while(rootIndex<preorder.length&&visited[rootIndex]){//从先序遍历数组里找根节点
                rootIndex++;
            }
            if(rootIndex<preorder.length){//根节点从先序遍历数组里找的,所以要保证不越界(先序遍历数组的界限)
                visited[rootIndex] = true;
                TreeNode root = new TreeNode(preorder[rootIndex]);
                int i=begin;
                for(;i<=end;i++){//从中序遍历数组中找根节点的左右子树
                    if(preorder[rootIndex]==inorder[i]){
                        break;
                    }
                }
                root.left = build(preorder,inorder,visited,begin,i-1);//连接根节点的左节点
                root.right = build(preorder,inorder,visited,i+1,end);//连接根节点的右节点
                return root;//返回根节点
            }else{
                return null;
            }
        }
    }
    思路:先序遍历会先访问根节点,所以我们可以根据先序遍历数组找到根节点,然后根据这个根节点来在中序遍历中找这个根节点的左子树和右子树,中序遍历中左边的序列都是左子树产生的序列,右边的序列都是右子树产生的序列,所以递归重构这些序列就行。
    需要放置越界
    时间复杂度:遍历了整个数组O(n)
    空间复杂度:需要一个额外的visited数组,O(n)
    
    0 赞同 0 条回复

# 回答此问题

后才能回答