算法学习 day3--重建二叉树

本题代码已上传到:gitbub

题目

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出图2.6所示的二叉树并输出它的头结点。

题目分析

在数据结构里讨论树的时候基本都是讨论二叉树,我们知道二叉树是一种特殊的树,其每个节点的子节点都不超过2个,而二叉树又可以引申出二叉搜索树,平衡二叉树(AVL树),红黑树等概念,关于树的参考。

此题目考察的是对二叉树的基本数据结构理解,及二叉树的遍历的理解。二叉树的遍历要掌握的主要是前/中/后序的遍历:
前序遍历:先访问根节点,再访问做节点,最后访问右节点;
中序遍历:先访问左节点,再访问根节点,最后访问右节点;
后序遍历:先访问左节点,再访问右节点,最后访问根节点;
层序遍历:从根开始,一层一层的遍历二叉树。(不常见,但是要知道概念)。

在二叉树的前序遍历中,第一个数字总是树的根节点。在中序遍历中,树的根节点在序列的中间,左子树的节点的值位于根节点的左边,右子树节点的值位于根节点值的右边。
所以重点就是:
根据前序序列找到根节点,然后在中序序列中找到根结点的位置,由此可以找到左子树的节点的个数和右子树节点的个数,然后在前序序列中找到左子树的根节点,再到中序序列中找到左子树的左子树和右子树。依次递归。

核心代码实现

 /**
     * 根据前序和中序序列重建二叉树
     *
     * @param preorder 前序序列
     * @param inorder  中序序列
     * @return 二叉树
     */
    private static BinaryTreeNode construct(int[] preorder, int[] inorder) {
        if (preorder == null || inorder == null || preorder.length != inorder.length || preorder.length <= 0) {
            throw new RuntimeException("Invalid input.");
        }

        return constructCode(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    }

    /**
     * 根据前序和中序序列重建二叉树
     *
     * @param preorder 前序序列
     * @param ps       前序遍历开始索引
     * @param pe       前序遍历结束索引
     * @param inorder  中序序列
     * @param is       中序遍历开始索引
     * @param ie       中序遍历结束索引
     * @return 二叉树
     */
    private static BinaryTreeNode constructCode(int[] preorder, int ps, int pe, int[] inorder, int is, int ie) {
        if (ps > pe || is > ie) {
            return null;
        }

        BinaryTreeNode node = new BinaryTreeNode();
        node.val = preorder[ps];

        if (ps == pe) {
            if (is == ie && preorder[ps] == inorder[is]) {
                return node;
            } else {
                throw new RuntimeException("Invalid input.");
            }
        }
        int idx = is;
        while (idx < ie && inorder[idx] != node.val) {
            ++idx;
        }
        if (idx == ie && inorder[idx] != node.val) {
            throw new RuntimeException("Invalid input.");
        }

        int leftLength = idx - is;
        if (leftLength > 0) {
            node.left = constructCode(preorder, ps + 1, ps + leftLength, inorder, is, idx - 1);
        }
        if (leftLength < pe - ps) {
            node.right = constructCode(preorder, ps + leftLength + 1, pe, inorder, idx + 1, ie);
        }

        return node;
    }

测试用例

   public static void main(String[] args) {
        //普通二叉树
        int[] preorder = {1, 2, 4, 7, 3, 5, 6, 8};
        int[] inorder = {4, 7, 2, 1, 5, 3, 8, 6};
        BinaryTreeNode root = construct(preorder, inorder);
        postorderPrint(root); //后序打印

        //所有节点都没有右节点
//        int[] preorder = {1, 2, 3, 4, 5};
//        int[] inorder = {5, 4, 3, 2, 1};
//        BinaryTreeNode root = construct(preorder, inorder);
//        postorderPrint(root); //后序打印

        //所有节点都没有左节点
//        int[] preorder = {1, 2, 3, 4, 5};
//        int[] inorder = {1, 2, 3, 4, 5};
//        BinaryTreeNode root = construct(preorder, inorder);
//        postorderPrint(root); //后序打印

        //只有一个节点
//        int[] preorder = {1};
//        int[] inorder = {1};
//        BinaryTreeNode root = construct(preorder, inorder);
//        postorderPrint(root); //后序打印

        //  完全二叉树
//        int[] preorder = {1, 2, 4, 5, 3, 6, 7};
//        int[] inorder = {4, 2, 5, 1, 6, 3, 7};
//        BinaryTreeNode root = construct(preorder, inorder);
//        postorderPrint(root); //后序打印

        //空指针
//        BinaryTreeNode root = construct(null, null);
//        postorderPrint(root); //后序打印

        //序列不匹配
//        int[] preorder = {1, 2, 4, 5, 3, 6, 7};
//        int[] inorder = {4, 2, 8, 1, 6, 3, 7};
//        BinaryTreeNode root = construct(preorder, inorder);
//        postorderPrint(root); //后序打印
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值