• 剑指 Offer 07. 重建二叉树


    题目

    力扣-剑指 Offer 07. 重建二叉树

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

    例如,给出
    
    前序遍历 preorder = [3,9,20,15,7]
    中序遍历 inorder = [9,3,15,20,7]
    返回如下的二叉树:
    
        3
       / 
      9  20
        /  
       15   7
     
    
    限制:
    
    0 <= 节点个数 <= 5000
    

    知识点

    • 二叉树的遍历顺序

    1,前序(Pre-order):根-左-右
    2,中序(In-order):左-根-右
    3,后序(Post-order):左-右-根

    题解

    难度为中等。

    解法一:递归

    按题目给的示例来划分:
    前序遍历划分 [ 3 | 9 | 20 15 7 ]
    中序遍历划分 [ 9 | 3 | 15 20 7 ]

    根据以上性质,可得出以下推论:

    • 前序遍历的首元素 为 树的根节点 node 的值。
    • 在中序遍历中搜索根节点 node 的索引 ,可将 中序遍历 划分为 [ 左子树 | 根节点 | 右子树 ] 。
    • 根据中序遍历中的左 / 右子树的节点数量,可将 前序遍历 划分为 [ 根节点 | 左子树 | 右子树 ] 。

    考虑通过递归对所有子树进行划分:

    • 递推参数: 根节点在前序遍历的索引 root 、子树在中序遍历的左边界 left 、子树在中序遍历的右边界 right ;

    • 终止条件: 当 left > right ,代表已经越过叶节点,此时返回 null ;

    • 递推工作:
      建立根节点 node : 节点值为 preorder[root] ;
      划分左右子树: 查找根节点在中序遍历 inorder 中的索引 i ;

    网上摘的保姆式的注解

    //Java借助Map版本 (Go的没写出来,等后面写出来了再更新)
    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        HashMap<Integer, Integer> map = new HashMap<>();//标记中序遍历
        int[] preorder;//保留的先序遍历,方便递归时依据索引查看先序遍历的值
    
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            this.preorder = preorder;
            //将中序遍历的值及索引放在map中,方便递归时获取左子树与右子树的数量及其根的索引
            for (int i = 0; i < inorder.length; i++) {
                map.put(inorder[i], i);
            }
            //三个索引分别为
            //当前根的的索引
            //递归树的左边界,即数组左边界
            //递归树的右边界,即数组右边界
            return recur(0,0,inorder.length-1);
        }
    
        TreeNode recur(int pre_root, int in_left, int in_right){
            if(in_left > in_right) return null;// 相等的话就是自己
            TreeNode root = new TreeNode(preorder[pre_root]);//获取root节点
            int idx = map.get(preorder[pre_root]);//获取在中序遍历中根节点所在索引,以方便获取左子树的数量
            //左子树的根的索引为先序中的根节点+1 
            //递归左子树的左边界为原来的中序in_left
            //递归右子树的右边界为中序中的根节点索引-1
            root.left = recur(pre_root+1, in_left, idx-1);
            //右子树的根的索引为先序中的 当前根位置 + 左子树的数量 + 1
            //递归右子树的左边界为中序中当前根节点+1
            //递归右子树的有边界为中序中原来右子树的边界
            root.right = recur(pre_root + (idx - in_left) + 1, idx+1, in_right);
            return root;
    
        }
    }
    

    leetcode-cn执行:

    执行用时:
    3 ms, 在所有 Java 提交中击败了55.11%的用户
    内存消耗:
    38.4 MB, 在所有 Java 提交中击败了80.00%的用户
    
    //Go,不借助Map版本
    /**
     * Definition for a binary tree node.
     * type TreeNode struct {
     *     Val int
     *     Left *TreeNode
     *     Right *TreeNode
     * }
     */
    func buildTree(preorder []int, inorder []int) *TreeNode {
        root := new(TreeNode)
        if len(preorder) == 0 {
            return nil
        }
        root_val := preorder[0]
        i := 0
        for inorder[i] != root_val {
            i++
        }
        left_tree := buildTree(preorder[1:i+1],inorder[:i])
        right_tree := buildTree(preorder[i+1:],inorder[i+1:])
        root.Val = root_val
        root.Left = left_tree
        root.Right = right_tree
        return root
    }
    

    leetcode-cn执行:

    执行用时:
    4 ms, 在所有 Go 提交中击败了95.75%的用户
    内存消耗:
    4.2 MB, 在所有 Go 提交中击败了25.36%的用户
    

    牛客网运行:

    运行时间:5ms
    超过39.31%用Go提交的代码
    占用内存:2344KB
    超过9.75%用Go提交的代码
    

    参考链接

    4种解法(递归,栈,队列),最后一种击败了100%的用户
    力扣官方题解
    【面试题】重建二叉树(解题思路分析+Java、Python实现+代码详细注释)
    面试题07. 重建二叉树(递归法,清晰图解)

             
    版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。
        
    特此声明:所有评论和私信都会在第一时间回复。也欢迎园子里和园子外的大大们指正错误,共同进步。或者直接私信我 (^∀^)
        
    声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!

    您的资助是我最大的动力!
    金额随意,欢迎来赏!

    如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的推荐按钮。
    如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

    如果,想给予我更多的鼓励,求打

    本博客的所有打赏均将用于博主女朋友的化妆品购买以及养肥计划O(∩_∩)O。我是【~不会飞的章鱼~】!

    联系或打赏博主【~不会飞的章鱼~】!https://www.cnblogs.com/OctoptusLian/

  • 相关阅读:
    pycharm 测试执行成功,但却无法成功生成测试报告(使用HTMLTestRunner)的解决办法
    Pycharm安装package报错:AttributeError: module 'pip' has no attribute 'main'
    解决pycharm新建工程项目都需要重新安装库问题
    使用grep排除空行和注释行
    Django实战(一)-----用户登录与注册系统5(图片验证码)
    Django实战(一)-----用户登录与注册系统4(表单)
    Django实战(一)-----用户登录与注册系统3(前端页面、登录视图)
    Django实战(一)-----用户登录与注册系统2(数据模型、admin后台、路由视图)
    Django实战(一)-----用户登录与注册系统1(环境搭建)
    python-----virtualenv 虚拟环境
  • 原文地址:https://www.cnblogs.com/OctoptusLian/p/14487847.html
Copyright © 2020-2023  润新知