xiaomi

个人博客

小米的个人博客,欢迎交流


每天一道剑指offer:重建二叉树


题目描述

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


解题思路

可以先自己尝试手画一遍,怎么根据前序和中序遍历结果画出原始的二叉树

前序遍历:根左右

中序遍历:左根右

可以知道在中序遍历中,根的位置可以分割左右子树,而前序遍历第一个节点就是根,这样可以初步分出最大的左右子树

按照这个方法,找到根的位置,继续在得到的左右子树中分割

代码

root.left = reBuild(pre, stPre + 1, i - stIn + stPre, in, stIn, i - 1)

stPre+1 :每次查找下一个点

i - stIn + stPre :搜题解这样写的,多画了几次发现确实是这样,但是自己不知咋推出来的,有大佬路过可以答疑解惑下 :)

root.right = reBuild(pre, i - stIn + stPre + 1, edPre, in, i + 1, edIn)

i - stIn + stPre + 1 :左子树+1就是右子树的开始

edPre :一直查到前序遍历的最后一个节点

    public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        if (pre.length == in.length && pre.length != 0) {
            TreeNode root = reBuild(pre, 0, pre.length - 1, in, 0, in.length - 1);
            return root;
        }

        return null;
    }

//    分割左右子树的递归过程
//    stPre:搜索前序遍历的起点  edPre:搜索前序遍历的终点
//    stIn/edIn以此类推
    public TreeNode reBuild(int[] pre, int stPre, int edPre, int[] in, int stIn, int edIn) {

        if (stPre > edPre || stIn > edIn) return null;
        
//        每次都new一个新的节点
        TreeNode root = new TreeNode(pre[stPre]);

//        查找根节点的for循环
        for (int i = stIn; i <= edIn; i++) {
//            如果满足条件,则该点就是根节点
            if (pre[stPre] == in[i]) {
//                递归左子树,分割分割再分割
                root.left = reBuild(pre, stPre + 1, i - stIn + stPre, in, stIn, i - 1);
//                递归右子树,分割分割再分割
                root.right = reBuild(pre, i - stIn + stPre + 1, edPre, in, i + 1, edIn);
            }
        }
        return root;
    }


Refer

重建二叉树(java版)

Log

  • 20190828 xiaomi init