剑指offer-重建二叉树

描述

给定某二叉树的前序遍历和中序遍历,请重建出该二叉树并返回。

public class ZYChongJianErChaShu {

    public static void main(String[] args){
        List<Integer> list = new ArrayList<>();
        TreeNode node = reConstructBinaryTree(new int[]{1, 2, 4, 7, 3, 5, 6, 8}, new int[]{4, 7, 2, 1, 5, 3, 8, 6});
        list = PrintFromTopToBottom(node);
        for(Integer i:list){
            System.out.println(i);
        }
    }
    /**
     * 关键是:利用前序序列根节点在前找到根节点,用根节点去中序序列划分成两部分,左部分是左子树,右部分是右子树。
     * 再利用子树长度去前序序列把前序序列中的左右子树找出来,同时可以找出根节点。递归进行此步骤,如果子树长度为0,则不需要生成子问题。
     */
    public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        TreeNode root = new TreeNode(pre[0]);
        build(root, pre, 0, pre.length, in, 0, in.length);
        return root;
    }
    /**
     * 递归和二分思想,将问题不断划分,直到问题容易解决。
     * 做法是:对于一个根节点,先去中序序列中找到根节点的值所在位置,利用这个位置分成2部分,左部分的中序序列长度即为前序序列中左部分的中序序列长度,右部分亦然。
     * 然后开始生成子问题,如果序列长度为0则不需要生成子问题。否则:利用前序序列第一个元素为根节点的性质生成根节点,然后构造子问题。
     * @param root 根节点
     * @param pre 前序序列 范围是[pleft,pright)
     * @param in 中序序列 范围是[ileft,iright)
     */
    public static void build(TreeNode root, int[] pre, int pleft, int pright, int[] in, int ileft, int iright) {
        int i;
        for (i = ileft; i < iright; i++) {
            if (in[i] == root.val) {//从中序序列寻找根节点的位置
                break;
            }
        }
        int t = i - ileft;
        if (t > 0) {//子树长度为0时不必生成子问题
            root.left = new TreeNode(pre[pleft + 1]);
            build(root.left, pre, pleft + 1, pleft + 1 + t, in, ileft, i);
        }

        if (pright - pleft - 1 - t > 0) {
            root.right = new TreeNode(pre[pleft + 1 + t]);
            build(root.right, pre, pleft + 1 + t, pright, in, i + 1, iright);
        }
    }

    public static class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
  }
    //广度优先
    public static ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> lists=new ArrayList<Integer>();
        if(root==null)
            return lists;
        Queue<TreeNode> queue=new LinkedList<TreeNode>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode tree=queue.poll();
            if(tree.left!=null)
                queue.offer(tree.left);
            if(tree.right!=null)
                queue.offer(tree.right);
            lists.add(tree.val);
        }
        return lists;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值