zoukankan      html  css  js  c++  java
  • leetcode-889-105-106-根据前-中-后遍历构造二叉树


    本题是leetcode,地址

    889. 根据前序和后序遍历构造二叉树

    105. 从前序与中序遍历序列构造二叉树

    106. 从中序与后序遍历序列构造二叉树

    题目

    889. 根据前序和后序遍历构造二叉树

    返回与给定的前序和后序遍历匹配的任何二叉树。

    pre 和 post 遍历中的值是不同的正整数。

    示例:

    输入:pre = [1,2,4,5,3,6,7], post = [4,5,2,6,7,3,1]
    输出:[1,2,3,4,5,6,7]

    提示:

    1 <= pre.length == post.length <= 30
    pre[] 和 post[] 都是 1, 2, ..., pre.length 的排列
    每个输入保证至少有一个答案。如果有多个答案,可以返回其中一个。

    根据一棵树的前序遍历与中序遍历构造二叉树。

    注意:
    你可以假设树中没有重复的元素。

    例如,给出

    105. 从前序与中序遍历序列构造二叉树

    前序遍历 preorder = [3,9,20,15,7]
    中序遍历 inorder = [9,3,15,20,7]
    返回如下的二叉树:
    3
    /
    9 20
    /
    15 7

    106. 从中序与后序遍历序列构造二叉树

    根据一棵树的中序遍历与后序遍历构造二叉树。

    注意:
    你可以假设树中没有重复的元素。

    例如,给出

    中序遍历 inorder = [9,3,15,20,7]
    后序遍历 postorder = [9,15,7,20,3]
    返回如下的二叉树:
    3
    /
    9 20
    /
    15 7

    分析

    其实这三道题非常类似,做题的前提是需要了解树的前序遍历、中序遍历、后续遍历的特点;

    • 前序遍历:遍历顺序,根-左-右;第一个节点就是根节点;
    • 中序遍历:遍历顺序,左-根-右;根节点是区分左右子树的节点;
    • 后续遍历:遍历顺序,左-右-根;由此可知,根节点在最后;

    [889. 根据前序和后序遍历构造二叉树]:

    根据前序遍历和后序遍历特点,我们找到前序遍历中的第一个非根节点在第二个节点的位置,就可以分别分离出:前序遍历:(根)(左子树)(右子树)和 (左子树)(右子树)(根),这样我们便得到一个根节点,分别对左子树和右子树进行递归操作,也可以分别获取到其根节点,如此便可得到一颗完整的树;

    同理我们可以分析出 前+中;中+后的推断逻辑;

    一位网友概括如下:

    前+后
    首先我们可以显然知道当前根节点为pre[pre_start],并且它在后序中的位置为post_end,因此这里我们需要找到能区分左右子树的节点。
    我们知道左子树的根节点为pre[pre_start+1],因此只要找到它在后序中的位置就可以分开左右子树(index的含义)
    前+中
    首先我们可以显然知道当前根节点为pre[pre_start],只用找出它在中序中的位置,就可以把左右子树分开(index的含义)
    中+后
    首先我们可以显然知道当前根节点为post[post_end],只用找出它在中序中的位置,就可以把左右子树分开(index的含义)

    code

        // 889. 根据前序和后序遍历构造二叉树
        public TreeNode constructFromPrePost(int[] pre, int[] post) {
            if(pre==null || pre.length==0) {
                return null;
            }
            TreeNode root = new TreeNode(pre[0]);
            int length = pre.length;
            if(length == 1) {
                return root;
            }
            for(int index =0; index < length; index ++) {
                if(pre[1] == post[index]) {
                    int[] pre_left = Arrays.copyOfRange(pre,1,index + 1 + 1);
                    int[] pre_right = Arrays.copyOfRange(pre,index + 1 + 1 ,length);
    
                    int[] post_left = Arrays.copyOfRange(post,0,index);
                    int[] post_right = Arrays.copyOfRange(post,index + 1, length -1);
    
                    root.left = constructFromPrePost(pre_left,post_left);
                    root.right = constructFromPrePost(pre_right,post_right);
                    break;
                }
            }
            return root;
        }
    
    
       // 105. 从前序与中序遍历序列构造二叉树
    	 public TreeNode buildTree(int[] preorder, int[] inorder) {
            if(preorder == null || preorder.length == 0) {
                return null;
            } 
           
            int length = preorder.length;  
            TreeNode root =  new TreeNode(preorder[0]);
            if(length == 1) {
                return root;
            }
    
            for(int index = 0; index < length; index ++) {
                if(root.val == inorder[index]) {
                    int[] preorder_left = Arrays.copyOfRange(preorder,1,index + 1);
                    int[] preorder_right = Arrays.copyOfRange(preorder,index + 1, length);
    
                    int[] inorder_left =  Arrays.copyOfRange(inorder,0,index);
                    int[] inorder_right = Arrays.copyOfRange(inorder,index + 1,length);
    
                    root.left = buildTree(preorder_left,inorder_left);
                    root.right = buildTree(preorder_right,inorder_right);
                    break;
                }
            }
            return root;
        }	
    
    
    
       // 106. 从中序与后序遍历序列构造二叉树
       public TreeNode buildTree(int[] inorder, int[] postorder) {
            if(postorder == null || postorder.length == 0) {
                return null;
            }
            
            int length = postorder.length;
            if(length == 1){
                 return new TreeNode(postorder[length -1]);
            }
    
            TreeNode root = new TreeNode(postorder[length - 1]);
            for(int index = 0; index < length; index ++) {
                if(postorder[length -1] == inorder[index]) {
                    int[] inorder_left = Arrays.copyOfRange(inorder,0,index);
                    int[] inorder_right = Arrays.copyOfRange(inorder,index + 1,length);
    
                    int[] postorder_left = Arrays.copyOfRange(postorder,0,index);
                    int[] postorder_right = Arrays.copyOfRange(postorder,index,length -1);
    
                    root.left = buildTree(inorder_left,postorder_left);
                    root.right = buildTree(inorder_right,postorder_right );
                    break;
                }
            }
    
            return root;
        }
    

    你的鼓励也是我创作的动力

    打赏地址

  • 相关阅读:
    C程序课题设计——基于图形界面开发的学生信息管理系统
    Linux系统的介绍(以下以Manjaro最新版为例子)
    linux环境下PS1变量配置
    C指针课题实验报告——职工工资管理系统
    vim系统配置文件,配置专属自己的环境
    git常用操作命令
    vim设置成类source insight功能,实现跳转和查找
    ext2文件系统学习札记
    【转载】解析Linux中的VFS文件系统机制
    linux中链表_队列等的基本原理以及操作以及堆栈
  • 原文地址:https://www.cnblogs.com/yangsanchao/p/13357647.html
Copyright © 2011-2022 走看看