力扣面试150题--从前序与中序遍历序列构造二叉树

Day 43

题目描述

思路(这题第一次没做出来,看了题解后理解)

做法哈希表+递归

首先复习一下前序遍历和中序遍历,
前序遍历 :中左右,这个不仅是遍历树的路线,同时对一个对于一个前序遍历的任意节点,存在这种关系如:

】 【该根的左子树 】 【该根的右子树
中序遍历 :左中右,同理如上,对于一个中序遍历的任意节点,存在这种关系如:

该根的左子树 】【 】【该根的右子树

好的这道题理解到这点就够,思路如下

  1. 根据前序遍历根总在最前面,确定一个根节点
  2. 根据这个根节点,在中序遍历中划分为左右两个子树
  3. 将该根的左孩子指向左子树的根,将该根的右孩子指向右子树的根
  4. 这样遍历前序序列结束,我们就能得到一棵完整的树

做法如下:由于我们取得根节点的值很容易,但是在中序遍历中找到这个根节点的序号很困难,于是事先用一个map(indexmap)存放每个节点对应的序号(这里主要是无重复元素)。

  1. 预存中序遍历中每个节点的序号到indexmap中
  2. 调用findroot(int[]preorder,int[]inorder,int preleft,int preright,int inleft,int inright),这里的preleft和preright是指前序遍历的范围,inleft和inright是指中序遍历的范围
  3. 以下介绍为这个函数的内容
  4. 首先判断前序遍历范围是否合法,不合法返回null
  5. 根据我们上面对前序遍历的复习,可知preleft指向的元素就是这个子树的根,通过indexmap查询这个根在中序遍历的序号in
  6. 根据这个根创建一个树节点
  7. 将它的左孩子指向root.left=findroot(preorder,inorder,preleft+1,preleft+in-inleft,inleft,in-1);,这里解释一下,preorder和inorder是前序遍历和后序遍历,(preleft+1,preleft+in-inleft)圈定的是前序遍历中左子树的范围,in-inleft的含义是找到左子树中的节点数量,(inleft,in-1)圈定的右子树的范围,in为根节点在中序遍历的序号,in-1就是中序遍历中左子树最后一个元素(具体看上面的中序遍历的复习)
  8. 同理将根节点的右孩子根据前序和中序规律指向。
  9. 最后就能得到整棵树
java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public Map<Integer, Integer> indexMap;
    public TreeNode findroot(int[]preorder,int[]inorder,int preleft,int preright,int inleft,int inright){
        if(preleft>preright){
            return null;
        }
        //前序遍历第一个元素就是根
        int root_num=preleft;
        int in=indexMap.get(preorder[root_num]);
        TreeNode root=new TreeNode(preorder[root_num]);
        root.left=findroot(preorder,inorder,preleft+1,preleft+in-inleft,inleft,in-1);
        root.right=findroot(preorder,inorder,preleft+in-inleft+1,preright,in+1,inright);
        return root;
    }
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        //做法就是找根做法
        int n=inorder.length;
        indexMap = new HashMap<Integer, Integer>();
        for(int i=0;i<n;i++){
            indexMap.put(inorder[i],i);
        }
        TreeNode root=findroot(preorder,inorder,0,n-1,0,n-1);
        return root;
    }
}
相关推荐
Coovally AI模型快速验证4 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·yolo·计算机视觉·transformer·无人机
pusue_the_sun4 小时前
数据结构:二叉树oj练习
c语言·数据结构·算法·二叉树
RaymondZhao345 小时前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt
艾伦~耶格尔5 小时前
【集合框架LinkedList底层添加元素机制】
java·开发语言·学习·面试
zhangfeng11335 小时前
DBSCAN算法详解和参数优化,基于密度的空间聚类算法,特别擅长处理不规则形状的聚类和噪声数据
算法·机器学习·聚类
一只叫煤球的猫5 小时前
🕰 一个案例带你彻底搞懂延迟双删
java·后端·面试
圣保罗的大教堂5 小时前
leetcode 2348. 全 0 子数组的数目 中等
leetcode
啊阿狸不会拉杆6 小时前
《算法导论》第 32 章 - 字符串匹配
开发语言·c++·算法
小学生的信奥之路6 小时前
洛谷P3817题解:贪心算法解决糖果分配问题
c++·算法·贪心算法
你知道网上冲浪吗7 小时前
【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
python·算法·数学建模·数值分析