重建二叉树


题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二节树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字


思路:前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序遍历结果,右部分为树的右子树中序遍历的结果


代码实现:

/**
 * 题目类型:二叉树
 *
 * 题目要求:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二节树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字
 *
 * 思路:前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,
 * 左部分为树的左子树中序遍历结果,右部分为树的右子树中序遍历的结果
 */
public class ReConstructBinaryTree {

    /**
     * 二叉树节点类
     */
    private static class TreeNode {
        int value;
        TreeNode left;
        TreeNode right;

        TreeNode(int value) {
            this.value = value;
        }
    }

    // 缓存中序遍历数组每个值对应的索引
    private static Map<Integer, Integer> indexForInOrders = new HashMap<>();


    private static TreeNode reconstructBinaryTree(int[] pre, int[] in) {
        if (pre == null || in == null || pre.length != in.length || in.length < 1) {
            return null;
        }

        for (int i = 0; i < in.length; i++)
            indexForInOrders.put(in[i], i);

        return reconstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1);
    }

    /**
     * 根据前序遍历数组的 [preL, preR] 和 中序遍历数组的 [inL, inR] 重新组建二叉树
     *
     * @param pre  前序遍历数组
     * @param preL 前序遍历数组的区间左端点
     * @param preR 前序遍历数组的区间右端点
     * @param in   中序遍历数组
     * @param inL  中序遍历数组的区间左端点
     * @param inR  中序遍历数组的区间右端点
     *
     * @return 新二叉树的根结点
     */
    private static TreeNode reconstructBinaryTree(int[] pre, int preL, int preR,int[] in,int inL, int inR) {

        // 开始位置大于结束位置说明已经没有需要处理的元素了
        if (preL > preR || inL > inR)
            return null;

        // 新二叉树的根节点为前序遍历数组中的第一个节点
        TreeNode root = new TreeNode(pre[preL]);

        // 找到中序遍历数组中根节点的索引,将数组分为两部分
        int inIndex = indexForInOrders.get(root.value);
        
        // 如果在整个中序遍历的数组中没有找到,说明输入的参数是不合法的,抛出异常
        if (inIndex > inR) {
            throw new RuntimeException("Invalid input");
        }
        
        // 新二叉树的左子树的节点数
        int leftTreeSize = inIndex - inL;
        root.left = reconstructBinaryTree(pre, preL + 1, preL + leftTreeSize, in, inL, inL + leftTreeSize - 1);
        root.right = reconstructBinaryTree(pre, preL + leftTreeSize + 1, preR, in, inL + leftTreeSize + 1, inR);
        return root;
    }

    /**
     * 中序遍历打印二叉树
     * @param root
     */
    private static void printTree(TreeNode root) {
        if (root != null) {
            printTree(root.left);
            System.out.print(root.value + " ");
            printTree(root.right);
        }
    }

    /**
     * 测试用例 1:普通二叉树
     */
    private static void test1() {
        int[] preorder = {1, 2, 4, 7, 3, 5, 6, 8};
        int[] inorder = {4, 7, 2, 1, 5, 3, 8, 6};
        TreeNode root = reconstructBinaryTree(preorder, inorder);
        printTree(root);
    }

    /**
     * 测试用例 2:完全二叉树
     *              1
     *            /   \
     *           2     3
     *          / \   / \
     *         4  5  6   7
     */
    private static void test2() {
        int[] preorder = {1, 2, 4, 5, 3, 6, 7};
        int[] inorder = {4, 2, 5, 1, 6, 3, 7};
        TreeNode root = reconstructBinaryTree(preorder, inorder);
        printTree(root);
    }

    /**
     * 测试用例 3 :所有节点都没有右子节点
     */
    private static void test3() {
        int[] preorder = {1, 2, 3, 4, 5};
        int[] inorder = {5, 4, 3, 2, 1};
        TreeNode root = reconstructBinaryTree(preorder, inorder);
        printTree(root);
    }

    /**
     * 测试用例 4:所有节点都没有左子节点
     */
    private static void test4() {
        int[] preorder = {1, 2, 3, 4, 5};
        int[] inorder = {1, 2, 3, 4, 5};
        TreeNode root = reconstructBinaryTree(preorder, inorder);
        printTree(root);
    }

    /**
     *  测试用例 5:树中只有一个节点
     */
    private static void test5() {
        int[] preorder = {1};
        int[] inorder = {1};
        TreeNode root = reconstructBinaryTree(preorder, inorder);
        printTree(root);
    }

    /**
     * 测试用例 6:二叉树的根节点指针为 null
     */
    private static void test6() {
        reconstructBinaryTree(null, null);
    }

    /**
     * 测试用例 7:输入的前序遍历序列和中序遍历序列不匹配
     */
    private static void test7() {
        int[] preorder = {1, 2, 4, 5, 3, 6, 7};
        int[] inorder = {4, 2, 8, 1, 6, 3, 7};
        TreeNode root = reconstructBinaryTree(preorder, inorder);
        printTree(root);
    }

    public static void main(String[] args) {

        System.out.print("测试用例 1:");
        test1();
        System.out.println();
        System.out.print("测试用例 2:");
        test2();
        System.out.println();
        System.out.print("测试用例 3:");
        test3();
        System.out.println();
        System.out.print("测试用例 4:");
        test4();
        System.out.println();
        System.out.print("测试用例 5:");
        test5();
        System.out.println();
        System.out.print("测试用例 6:");
        test6();
        System.out.println();
        //System.out.print("测试用例 7:");
        //test7();
    }
}

// 输出结果
测试用例 1:4 7 2 1 5 3 8 6 
测试用例 2:4 2 5 1 6 3 7 
测试用例 3:5 4 3 2 1 
测试用例 4:1 2 3 4 5 
测试用例 5:1 
测试用例 6:

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 题目:重建二叉树 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍...
    后浪普拉斯阅读 3,938评论 0 0
  • 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重...
    levinhax阅读 3,106评论 0 0
  • 写在前面: 为了增长一下自己的数据结构能力,也为了面试准备,准备将剑指Offer做一下,并与各位分享,希望各位可以...
    z七夜阅读 2,490评论 0 2
  • 题目描述输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的...
    星空_ad64阅读 3,780评论 0 0
  • 题目输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字...
    qming_c阅读 2,256评论 0 0

友情链接更多精彩内容