【LeetCode】拥有它构造二叉树不是梦(105,106,889题)

构造二叉树

想必大家都在为构造二叉树而烦恼。

这篇文章只用一种方法,解决知道两种遍历方式,构造二叉树。

105. 从前序与中序遍历序列构造二叉树
106. 从中序与后序遍历序列构造二叉树
889. 根据前序和后序遍历构造二叉树

这三道题目都有一个相同之处,就是要找出根节点来,然后针对这个根节点,不断地递归寻找本节点的左子树,右子树。

这三题的基本思想就是用map维护一下位置,然后进行不断地递归

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

105题是知道前序中序构建

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

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

通过观察我们发现前序的第一个就是根节点,通过根节点在从中序遍历中找到相应的位置,左边就是左子树元素,右边就是右子树元素。

private HashMap<Integer,Integer> map;
public TreeNode BuildTree(int[] preporder,int[] inorder,int pl,int pr,int il,int ir){
    if(il>ir)
        return null;

    TreeNode root = new TreeNode(preporder[pl]);
    int io=map.get(preporder[pl]);
    int nums=io-il;
    root.left=BuildTree( preporder, inorder,pl+1,pr+nums,il,io-1);
    root.right=BuildTree(preporder,inorder,pl+nums+1,pr,io+1,ir);
    return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
    int n=inorder.length;
    map = new HashMap<Integer, Integer>();
    for (int i = 0; i < n; i++) {
        map.put(inorder[i],i);
    }
    return BuildTree(preorder,inorder,0,n-1,0,n-1);
}

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

通过观察我们发现后序的最后就是根节点,通过根节点在从中序遍历中找到相应的位置,左边就是左子树元素,右边就是右子树元素。

例如,给出

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

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7
private HashMap<Integer,Integer> map;
public TreeNode BuildTree(int[] inorder,int[] postorder,int il,int ir,int pl,int pr){
    if(il>ir)
        return null;
    int ro=map.get(pr);
    int nums=ro-il;
    TreeNode root=new TreeNode(postorder[pr]);
    root.left=BuildTree(inorder,postorder,il,ro-1,pl,pl+nums);
    root.right=BuildTree(inorder,postorder,ro+1,ir,pl+nums+1,pr);
    return root;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
    int n=inorder.length;
    map = new HashMap<Integer, Integer>();
    for (int i = 0; i < n; i++) {
        map.put(inorder[i],i);
    }
    return BuildTree(inorder,postorder,0,n-1,0,n-1);
}

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

前序:pre = [1,2,4,5,3,6,7]
后续:post = [4,5,2,6,7,3,1]
输出:[1,2,3,4,5,6,7]

通过观察我们发现这一题和前两题不一样了,我们很难观察左子树的序列,与右子树的序列,我们只能看出,前序遍历的第一个,后序的最后一个是根节点。

但是我们比较发现,前序遍历的第二个元素,然后找到后续遍历的位置,他左边就是左子树元素,右边就是右子树(除最后一个元素)元素。

private HashMap<Integer,Integer> map;
public TreeNode BuildTree(int[] pre,int[] post,int prel,int prer,int postl,int postr){
    if(prel>prer)
        return null;
    TreeNode root=new TreeNode(pre[prel]);
    if(prel==prer){
        return root;
    }
    int ro=map.get(pre[prel+1]);
    int nums=ro-postl+1;
    root.left=BuildTree(pre,post,prel+1,prel+nums,postl,ro);
    root.right=BuildTree(pre,post,prel+nums+1,prer,ro+1,postr-1);
    return root;
}
public TreeNode constructFromPrePost(int[] pre, int[] post) {
    map=new HashMap<Integer,Integer>();
    int n=post.length-1;
    for(int i=0;i<=n;i++){
        map.put(post[i],i);
    }
    return BuildTree(pre,post,0,n,0,n);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值