【2】【leetcode-105,106】 从前序与中序遍历序列构造二叉树,从中序与后序遍历序列构造二叉树

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

(没思路,典型记住思路好做)

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / 
  9  20
    /  
   15   7

链接:https://www.nowcoder.com/questionTerminal/0ee054a8767c4a6c96ddab65e08688f4
来源:牛客网

 
/*
     * 假设树的先序遍历是12453687,中序遍历是42516837。
     * 这里最重要的一点就是先序遍历可以提供根的所在,
     * 而根据中序遍历的性质知道根的所在就可以将序列分为左右子树。
     * 比如上述例子,我们知道1是根,所以根据中序遍历的结果425是左子树,而6837就是右子树。
     * 接下来根据切出来的左右子树的长度又可以在先序便利中确定左右子树对应的子序列
     * (先序遍历也是先左子树后右子树)。
     * 根据这个流程,左子树的先序遍历和中序遍历分别是245和425,
     * 右子树的先序遍历和中序遍历则是3687和6837,我们重复以上方法,可以继续找到根和左右子树,
     * 直到剩下一个元素。
     */
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTree(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }
 
    private TreeNode buildTree(int[] preorder, int preLeft, int preRight, int[] inorder, int inLeft, int inRight) {
        if(preRight<preLeft)
            return null;
        TreeNode node=new TreeNode(preorder[preLeft]);
        if(preRight==preLeft)
            return node;
        int num=0;
        for(int i=inLeft;i<=inRight;i++){
            if(inorder[i]==preorder[preLeft]){
                num=i;
                break;
            }
        }
        int length=num-inLeft;
         
        node.left=buildTree(preorder,preLeft+1,preLeft+length,inorder,inLeft,inLeft+length-1);
        node.right=buildTree(preorder,preLeft+length+1,preRight,inorder,num+1,inRight);
         
        return node;
    }

看了答案自己写,边界条件老是搞错:

public class ConstructBinaryTree {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder.length <=0 || inorder.length<=0){
            return null;
        }
       return helper(preorder,0,preorder.length-1,inorder,0,inorder.length-1);

    }

    public TreeNode helper(int[] preorder,int i,int j, int[] inorder,int m,int n) {
        if (i>j) {
            return null;
        }
        int root = preorder[i];
        TreeNode node = new TreeNode(root);
        int leftlength = 0;
        for (int k=m;k<=n;k++) {
            if (root == inorder[k]) {
                leftlength = k-m;
            }
        }
        node.left = helper(preorder, i+1, i+leftlength,inorder, m, m+leftlength-1);
        node.right = helper(preorder, i+leftlength+1, j,inorder, m+leftlength+1, n);
        return node;
    }
}

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

根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]

返回如下的二叉树:

    3
   / 
  9  20
    /  
   15   7


与105从前序与中序遍历序列构造二叉树的区别就是后序序列最后一个是根节点,其他一样