zoukankan      html  css  js  c++  java
  • 剑指 Offer 07. 重建二叉树

    输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。

    假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

    例如,给出

    前序遍历 preorder = [3,9,20,15,7]
    中序遍历 inorder = [9,3,15,20,7]

    返回如下的二叉树:

        3
       / 
      9  20
        /  
       15   7

    限制:

    0 <= 节点个数 <= 5000

    题解:

    递归方式
    先根据先序遍历确认根节点,然后找出根节点在中序遍历的位置,从而确定左子树的长度和右子树的长度,对应到先序遍历中也能找出对应的左子树和右子树,
    分别递归左子树和右子树,重复上面步骤

    例如:

    上面示例所示:

    第一次递归:

    由先序遍历知:3为根节点,

    由中序遍历知,左子树有1个,为9;右子树有3个,为15,20,7

    第二次递归:

      左子树递归:

        先序遍历中,左子树为9,由此,根节点为9

        因为中序遍历中9也是根节点。

        由此,确认9为跟节点。

      右子树遍历:

        先序遍历中,右子树为20,15,7,由此,20为根节点。

        中序遍历中,则找到20的根节点,则左子树为15,右子树为7.

    代码:

    public class offer07 {
    
        private static Map<Integer,Integer> indexMap;
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            int[] preorder = new int[]{3,9,20,15,7};
            int[] inorder = new int[]{9,3,15,20,7};
            TreeNode tree = buildTree(preorder,inorder);
            System.out.println(tree);
        }
    
        /**
         * 思路:主要是递归的定位到根节点
         * @param preorder
         * @param inorder
         * @return
         */
        public static TreeNode buildTree(int[] preorder, int[] inorder) {
            int n = preorder.length;
            //构造哈希映射,帮助我们快速定位根节点
            indexMap = new HashMap<Integer,Integer>();
            for(int i=0;i<n;i++){
                indexMap.put(inorder[i], i);
            }
            return myBuildTree(preorder,inorder,0,n-1,0,n-1);
        }
        
        
        /**
         * 递归方式
         * 先根据先序遍历确认根节点,然后找出根节点在中序遍历的位置,从而确定左子树的长度和右子树的长度,对应到先序遍历中也能找出对应的左子树和右子树,
         * 分别递归左子树和右子树,重复上面步骤。
         * 
         * @param preorder
         * @param inorder
         * @param preorder_left
         * @param preorder_right
         * @param inorder_left
         * @param inorder_right
         * @return
         */
        public static TreeNode myBuildTree(int[] preorder,int[] inorder,int preorder_left,int preorder_right,int inorder_left,int inorder_right){
            if(preorder_left>preorder_right){
                return null;
            }
            
            //前序遍历中的第一个节点就是根节点
            int preorder_root = preorder_left;
            //在中序遍历中定位根节点
            int inorder_root = indexMap.get(preorder[preorder_root]);
            
            //先把根节点建立出来
            TreeNode root = new TreeNode(preorder[preorder_root]);
            //得到左子树中的节点数目
            int size_left_subtree = inorder_root - inorder_left;
            //递归的构造左子树,并连接到根节点
            //先序遍历中【从左边界+1 开始的size_left_subtree】个元素就对应了中序遍历中【从左边界开始到根节点定位-1】的元素
            root.left = myBuildTree(preorder,inorder,preorder_left+1,preorder_left+size_left_subtree,inorder_left,inorder_root-1);
            
            //递归的构造右子树,并连接到根节点
            //先序遍历中【 从左边界+1  + 左子树节点数目  对应 开始 到右边界】的元素对应了中序遍历中  【从左边界开始 到 根节点-1】的元素
            root.right = myBuildTree(preorder,inorder,preorder_left+size_left_subtree+1,preorder_right,inorder_root+1,inorder_right);
            
            return root;
        }
        
        
    }
    
    class TreeNode{
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x){
            val = x;
        }
    }
  • 相关阅读:
    easyui_1
    JSONOBJECT
    基础回顾—list遍历4种
    <input type=file>上传唯一控件
    window.open
    poi--导入
    java字符串的替换
    一、IIS搭建前端静态模板_资源加载问题
    一、ASP.NET Iframework_SignalR集线器类(v2)
    一、ASP.NET Iframework_SignalR永久连接类(v2)
  • 原文地址:https://www.cnblogs.com/Vincent-yuan/p/14942550.html
Copyright © 2011-2022 走看看