(前序·中序 || 中序·后序 || 前序·后序 || 先序)构造二叉树

前序·中序

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
  • 使用哈希表,构造哈希映射,快速定位根节点(省时)
  • 前序遍历第一个节点即为根节点,对应找到中序遍历中根节点位置和左子树中节点数目
  • 递归构造左右子树
/**
 - Definition for a binary tree node.
 - public class TreeNode {
 -     int val;
 -     TreeNode left;
 -     TreeNode right;
 -     TreeNode(int x) { val = x; }
 - }
 */
class Solution {
    Map<Integer,Integer> map;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map=new HashMap<Integer,Integer>();
        for(int i=0;i<preorder.length;i++){
            //构造哈希映射,快速定位根节点
            map.put(inorder[i],i);//键值对:键表示一个节点的值,值表示其在中序遍历中的出现位置。
        }
        return solve(preorder,inorder,0,preorder.length-1,0,preorder.length-1);
    }
    public TreeNode solve(int[] preorder,int[] inorder,int prel,int prer,int inl,int inr){
        if(prel>prer){return null;}
        int preroot=prel;  //前序遍历中第一个位置就是根节点
        int inroot=map.get(preorder[preroot]);  //中序遍历中找到根节点位置
        TreeNode root=new TreeNode(preorder[preroot]);  //建立根节点
        int len=inroot-inl;  //左子树长度
        //递归构造左右子树
        root.left=solve(preorder,inorder,prel+1,prel+len,inl,inroot-1);
        root.right=solve(preorder,inorder,prel+len+1,prer,inroot+1,inr);
        return root;
    }
}

中序·后序

根据一棵树的中序遍历与后序遍历构造二叉树。(无重复元素)
  • 后序遍历最后一个元素即为根节点,由此在中序遍历中找到根节点位置
  • 根据根节点位置将中序遍历分成左子树和右子树
  • 递归构造左右子树

注意左右边界(当前位置+长度-1)

/**
 - Definition for a binary tree node.
 - public class TreeNode {
 -     int val;
 -     TreeNode left;
 -     TreeNode right;
 -     TreeNode(int x) { val = x; }
 - }
 */
class Solution {
    Map<Integer,Integer> map=new HashMap<>();
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for(int i=0;i<inorder.length;i++){
            map.put(inorder[i],i);
        }
        return solve(inorder,postorder,0,inorder.length-1,0,inorder.length-1);
    }
    public TreeNode solve(int[] inorder,int[] postorder,int inl,int inr,int postl,int postr){
        if(postl>postr){return null;}
        int postroot=postr;  //后序遍历最后一个元素即为根节点
        int inroot=map.get(postorder[postroot]);  //在中序遍历中找到根节点位置
        TreeNode root=new TreeNode(postorder[postroot]);
        int len=inroot-inl;
        //递归构造左子树·右子树
        root.left=solve(inorder,postorder,inl,inroot-1,postl,postl+len-1);
        root.right=solve(inorder,postorder,inroot+1,inr,postl+len,postr-1);
        return root;
    }
}

前序·后序

返回与给定的前序和后序遍历匹配的任何二叉树。pre 和 post 遍历中的值是不同的正整数。
  • 前序第一个元素(后序最后一个节点)即为根节点
  • 关键如何找到左子树的长度----(前序遍历中第二个元素在后序遍历中是左子树的根节点)
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode constructFromPrePost(int[] pre, int[] post) {
        return solve(pre,post,0,pre.length-1,0,pre.length-1);
    }
    public TreeNode solve(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;}  //只有一个节点时直接返回根
        for(int i=postl;i<=postr;i++){
            if(post[i]==pre[prel+1]){   //前序遍历第二个元素在后序遍历中为左子树的根节点
                int len=i-postl+1;    //由此求出左子树长度
                root.left=solve(pre,post,prel+1,prel+len,postl,i);
                root.right=solve(pre,post,prel+len+1,prer,i+1,postr-1);
                return root;
            }
        }
        return null;
    }
}

返回与给定先序遍历 preorder 相匹配的二叉搜索树(binary search tree)的根结点。

  • 先序遍历第一个元素就是根节点
  • 左子树所有节点均小于根节点,右子树所有节点均大于根节点
/**
 * 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 {
    public TreeNode bstFromPreorder(int[] preorder) {
        return solve(preorder,0,preorder.length-1);
    }
    public TreeNode solve(int[] preorder,int start,int end){
        if(start>end){return null;}
        TreeNode root=new TreeNode(preorder[start]);  //先序序列第一个节点为根节点
        int i=start+1;
        //左子树所有节点小于根节点,右子树所有节点大于根节点
        while(i<preorder.length && preorder[i]<root.val){i++;}  //找到左子树范围
        //递归构建左右子树
        root.left=solve(preorder,start+1,i-1);
        root.right=solve(preorder,i,end);
        return root;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值