105. Construct Binary Tree from Preorder and Inorder Traversal

https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/

106. Construct Binary Tree from Inorder and Postorder Traversal

https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/

889. Construct Binary Tree from Preorder and Postorder Traversal

https://leetcode.com/problems/construct-binary-tree-from-preorder-and-postorder-traversal

 

Note: 这三道题前提都是pre/inorder/post order 数组里的 num 都是distinct, 否则算法无法执行。

 

105/106: 这两题几乎一样,105 是给出preorder and inorder 求Tree, 106 是给出 postorder and inorder 求Tree ,共同点都是 具备inorder. 

以105为例, preorder: root-->left-->right, 因此pre[0] 一定是root, 然后 后面的是 left and right,关键问题在于不知道从哪去划分left and right. 

                     inorder: left-->root--->right,  因此只要找到root, 然后root 左边为 left, 右边为right, 关键问题是不知道root 的位置。 

                     因此,结合preorder and inorder, 可以先通过pre[0] 确定 root 是谁,然后 在inorder 中找到root 位置,从而划分左右子树。

106 如果是 postorder, 那么 post[N-1] 为 root, 通过  inorder 找到root 位置再划分左右子树。

 

For example, given

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]

Return the following binary tree:

    3
   / \
  9  20
    /  \
   15   7

root pre[0] =3, inorder.indexOf(pre[0]=3) 确定 3的 index, 因此 left tree = [9] right tree=[15 20 7]
因此设计一个 dfs 函数:
dfs(int start_pre, int start_in, int end_in, int[] pre, int[] inorder)
注意 对于 preorder数组 ,只需要知道 start_pre 就够了,因为从start_pre 得到root信息。

class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {

    return helper(0, 0, inorder.length - 1, preorder, inorder);
}

public TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder) {
     if(preStart > preorder.length-1){ //仅仅处理 preorder = []的情况
       return null;
    }
    
    TreeNode root = new TreeNode(preorder[preStart]);
    // find root index 
    int index = inStart;
    for(; index<=inEnd && inorder[index] != root.val;) {index++;}
    
    //index-1 < inStart 说明左子树不存在,也可以在 递归出口时判断
    root.left =  index -1 <inStart ? null:  helper(preStart+ 1, inStart, index-1, preorder, inorder);
    // index+1 > inEnd 说明右子树不存在,,也可以在 递归出口时判断
    // preStart+ index-inStart +1 : preStart +1 + leftTree_len = preStart+1+ (index-1-inStart +1) 
    root.right = index+1 > inEnd ?  null:   helper(preStart+ index-inStart +1, index+1, inEnd, preorder, inorder);
        
    return root;    
}
    
}

这里唯一需要小心的是计算 root,right 时, preorder 的start index : preStart+ index-inStart +1

计算过程: left_tree start index = preStart+1,  然后 left tree 长度为:  index- instart, 因此  right tree start index 为 

preStart+ index-inStart +1

优化:上面算法每次需要一个for 循环寻找 root 在 inorder 里的index, 因此可以用一个map 去优化,避免用for 循环去查询。上面的算法只排名40% 左右, 而用map 优化后可以 排名97%

class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
    
     Map<Integer,Integer> map_in = new HashMap<>(); // val+index
     for(int i=0; i<inorder.length; i++){
        map_in.put(inorder[i],i); 
     }

    return helper(0, 0, inorder.length - 1, preorder, inorder,map_in);
}

public TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder,Map<Integer,Integer> map_in) {
     if(preStart > preorder.length-1){ //仅仅处理 preorder = []的情况
       return null;
    }
    
    TreeNode root = new TreeNode(preorder[preStart]);
    // find root index 
    int index = map_in.get(root.val);
    //for(; index<=inEnd && inorder[index] != root.val;) {index++;}
    
    //index-1 < inStart 说明左子树不存在,也可以在 递归出口时判断
    root.left =  index -1 <inStart ? null:  helper(preStart+ 1, inStart, index-1, preorder, inorder,map_in);
    // index+1 > inEnd 说明右子树不存在,,也可以在 递归出口时判断
    // preStart+ index-inStart +1 : preStart +1 + leftTree_len = preStart+1+ (index-1-inStart +1) 
    root.right = index+1 > inEnd ?  null:   helper(preStart+ index-inStart +1, index+1, inEnd, preorder, inorder,map_in);
        
    return root;    
}
    
}

 

106 和105类似,不再分析,代码如下:

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
    
        Map<Integer, Integer> map_in = new HashMap<>();
        int len = postorder.length;
        for(int i=0; i<len; i++) map_in.put(inorder[i],i);
      
        return  helper(len-1, 0,len-1, inorder, postorder, map_in) ;
        
    }
    
    private TreeNode helper(int poEnd, int inStart, int inEnd,  int[] inorder, int[] postorder, Map<Integer,Integer> map_in){
       if(inStart > inEnd) { //包含了了 order = []的情况了
           return null;
       }
        
        TreeNode root = new TreeNode(postorder[poEnd]);
        int index = map_in.get(root.val);
        
        //System.out.println("poEnd: "+ poEnd + " inStart: "+ inStart+ " inEnd: "+ inEnd + " index: "+ index);
        root.left =  helper(poEnd-inEnd+index-1, inStart, index-1, inorder, postorder, map_in);
        root.right =   helper(poEnd-1, index+1,inEnd,inorder,postorder,map_in);   
        return root;
    }
}

 


 
posted on 2018-11-06 15:16  KeepAC  阅读(112)  评论(0编辑  收藏  举报