java数据结构与算法刷题-----LeetCode106. 从中序与后序遍历序列构造二叉树

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

在这里插入图片描述

1. 法一:递归

解题思路:时间复杂度O(n),空间复杂度O(n),空间使用了一个Map,大小为中心遍历的长度,以及递归需要的栈空间
  1. 因为后序遍历[9,15,7,20,3]是左右中,它表示一个区间中,最后一个结点,是中间结点。比如[9,15,7,20,3]这个区间,正好是整个二叉树,共5个结点。那么这个区间的中间结点,也就是根节点为最后一个结点3.
  2. 而中序遍历[9,3,15,20,7]是左中右,它表示,只要找到中间结点,就可以分出左右两个区间来,比如[9,3,15,20,7]这个区间,已知3是根节点,那么[9]在其左子树,[15,20,7]在其右子树
  3. 所以思路很简单,我们先通过后序遍历序列,在区间中拿到最后一个结点,从而获取中间结点。然后通过中序遍历序列,获得其左右两个区间
  4. 然后其左右两个区间,因为后序遍历是左右中,中确定后,先确定右区间。

继续从后序遍历序列中,获取其最后一个结点20,20就是这个右子树的中间结点。

  1. 然后构造其左区间。依次类推,直到整颗二叉树完成构造。

后序遍历序列只需要从后往前依次遍历即可,因为只需要你做一遍后序遍历,就会发现,后序遍历的效果就是每一个中间结点,都按顺序排列在序列末尾

  1. 比如[9,15,7,20,3],根节点为3,3的右子树为20,20的右子树为7,此时通过中序遍历发现右边到头了
  2. 开始左子树构造,20的左子树为15, 然后15到头了。回到3 , 最后3的左子树为9. 9也到头了,没有结点了,构造完成

所以一定要注意,拿到中间结点后,先去右区间,右区间遍历完成后,再去左区间

代码

在这里插入图片描述

/**
 * 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 {
    int post_idx;//当前区间中结点的位置
    int[] postorder;//后序遍历
    int[] inorder;//中序
    //保存中序遍历中,每个结点在inorder数组中的下标
    Map<Integer, Integer> idx_map = new HashMap<Integer, Integer>();
    //后序:左右中
    //中序:左中右
    //每次确定一个“中”
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        this.postorder = postorder;
        this.inorder = inorder;
        // 从后序遍历的最后一个元素开始:因为后序:左右中,中结点始终在区间最后面
        post_idx = postorder.length - 1;

        // 建立(元素,下标)键值对的哈希表,保存中序inorder数组的结点下标位置
        int idx = 0;
        for (Integer val : inorder) {
            idx_map.put(val, idx++);
        }
        //helper通过中序和后序遍历构造二叉树,
        //每次在中序遍历的inorder数组规定区间,初始是全部从0到inorder.length-1
        //然后从后序遍历中获取中结点。
        return helper(0, inorder.length - 1);
    }

    public TreeNode helper(int in_left, int in_right) {
        // 如果这里没有节点构造二叉树了,就结束
        if (in_left > in_right) {
            return null;
        }

        // 选择 post_idx 位置的元素作为当前子树根节点
        int root_val = postorder[post_idx];//中结点,从后序遍历中获取
        TreeNode root = new TreeNode(root_val);

        // 根据 root 所在位置分成左右两棵子树
        int index = idx_map.get(root_val);//获取此结点在中序遍历中的位置
        //从而得到以此结点为中心的左右两个区间

        // 下标减一
        post_idx--;//下标前移,找到下一个中结点
        // 先构造右子树(先右区间)
        root.right = helper(index + 1, in_right);//进入当前中结点的右区间,再次构造
        // 构造左子树(然后再左区间)
        root.left = helper(in_left, index - 1);//进入当前中结点的左区间,再次构造
        return root;//返回当前root结点(中结点)。最终一定会返回根节点
    }

    
}

2. 法二:迭代

思路分析:时间复杂度O(n),空间复杂度O(n),空间只用了队列来模拟递归的栈,无需map
  1. 将中序和后序都反过来:中序变为右中左,后序变成右左中
  2. 初始我们可以直接通过后序获取根结点root
  3. 而如果我们倒着遍历中序序列的话,正好获得到root的右区间
  4. 当我们发现倒着遍历中序,找到了root,那么剩下的是左区间的
  5. 然后重复这个过程即可
代码

在这里插入图片描述

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if (postorder == null || postorder.length == 0) {//没有结点直接返回null
            return null;
        }
        //后序序列最后一个,必然是根节点
        TreeNode root = new TreeNode(postorder[postorder.length - 1]);//根节点
        Deque<TreeNode> stack = new LinkedList<TreeNode>();//模拟栈
        stack.push(root);//根结点先入栈,是迭代法必须得
        int inorderIndex = inorder.length - 1;//中序遍历的下标
        for (int i = postorder.length - 2; i >= 0; i--) {//除去根节点外,依次从后往前遍历postorder后序序列
            int postorderVal = postorder[i];//获取后序序列,中结点
            TreeNode node = stack.peek();//获取栈顶元素
            //下面的inorder[inorderIndex],指向的是当前node中间结点的右区间最后一个元素
            if (node.val != inorder[inorderIndex]) {//如果栈顶不是中间结点,直到中序遍历找到中间
                node.right = new TreeNode(postorderVal);//那么先处理右区间
                stack.push(node.right);//入队列
            } else {//如果栈顶就是中间结点
                //如果没有遍历完成,并且栈顶就是当前中序遍历中间结点的话
                while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
                    node = stack.pop();//出栈这个中间结点node1,它们已经构造完成了右子树,该处理它的左子树了
                    inorderIndex--;//但是如果inorderIndex再次对上栈顶,说明node1这个结点没有左子树,还会继续while循环
                }
                //然后处理左区间
                node.left = new TreeNode(postorderVal);
                stack.push(node.left);
            }
        }
        return root;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/409245.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能 — 相机模型和镜头畸变

目录 一、相机模型1、相机与图像2、坐标系1、世界坐标系2、相机坐标系3、图像物理坐标系4、图像像素坐标系 3、相机成像4、世界坐标系到摄像机坐标系5、欧氏变换6、齐次坐标7、摄像机坐标系到图像物理坐标系8、图像物理坐标系到图像像素坐标系9、摄像机坐标系到图像像素坐标系1…

图解目标检测 之 【YOLOv9】 算法 最全原理详解

YOLOv9与SOTA模型对比 什么是 YOLOv9&#xff1f;YOLOv9是YOLO系列中的最新产品&#xff0c;是一种实时目标检测模型。它通过先进的深度学习技术和架构设计&#xff0c;包括通用 ELAN (GELAN) 和可编程梯度信息 (PGI)&#xff0c;展现出更好的性能。 YOLO 系列通过引入计算机视…

C++入门学习(三十七)函数分文件编写【DEV】

创建.h后级名的头文件创建.cpp后缀名的源文件在头文件中写函数的声明在源文件中写函数的定义 一、选择文件、新建、项目 二、 选择Empty Project 三、 新建源文件New File 四、贴代码 test.cpp #include <iostream> #include "add.h" using namespace std;i…

在Sora引爆视频生成时,Meta开始用Agent自动剪视频了

未来&#xff0c;视频剪辑可能也会像视频生成领域一样迎来 AI 自动化操作的大爆发。 这几天&#xff0c;AI 视频领域异常地热闹&#xff0c;其中 OpenAI 推出的视频生成大模型 Sora 更是火出了圈。而在视频剪辑领域&#xff0c;AI 尤其是大模型赋能的 Agent 也开始大显身手。 …

PMP项目管理考试要注意些什么?

PMP考试和PMP备考过程中应该注意哪些问题&#xff1f; PMP备考完成后就要迎接实战考试了&#xff0c;考试前千万不要有多余的想法&#xff0c;顺其自然就行了&#xff0c;我想大家各种紧张、各种忧虑的原因大抵是因为考试成本考&#xff0c;担心考不过&#xff0c;其实只要你在…

Java后端服务接口性能优化常用技巧

接口性能优化常用技巧 前言1.数据库索引2.慢SQL优化3.异步执行4.批量处理5.数据预加载6.池化技术&#xff08;多线程&#xff09;8.事件回调机制9.串行改为并行调用10.深度分页问题 前言 对于高标准程序员来说提供高性能的服务接口是我们所追求的目标&#xff0c;以下梳理了一…

Linux安装Zookeeper

目录 下载配置启动 下载 下载链接 https://archive.apache.org/dist/zookeeper/上传 我直接本地下好了&#xff0c;拖到对应文件夹解压&#xff0c;重命名&#xff0c;注意路径 tar -zxvf /opt/Zookeeper/apache-zookeeper-3.7.2-bin.tar.gz -C /opt/ mv /opt/apache-zookeep…

WPF真入门教程29--MVVM常用框架之MvvmLight

1、MVVM模式回顾 关于mvvm模式的基础知识&#xff0c;请看这2个文章&#xff1a; WPF真入门教程23--MVVM简单介绍 WPF真入门教程24--MVVM模式Command命令 做过VUE开发或微信小程序开发的伙伴&#xff0c;就知道MVVM模式&#xff0c;核心就是数据驱动控件&#xff0c;全栈开…

【EAI 025】Ego4D: Around the World in 3,000 Hours of Egocentric Video

Paper Card 论文标题&#xff1a;Ego4D: Around the World in 3,000 Hours of Egocentric Video 论文作者&#xff1a;Kristen Grauman, Andrew Westbury, Eugene Byrne, et al. 作者单位&#xff1a;UC Berkeley, CMU, Google 论文原文&#xff1a;https://arxiv.org/abs/2110…

【MySQL高可用集群】MySQL的MGR搭建

前情提要&#xff1a; MySQL官方在 5.7.17版本正式推出组复制&#xff08;MySQL Group Replication&#xff0c;简称MGR&#xff09;&#xff0c;使用类似 zookeeper 的多于一半原则。在一个集群由 2N1 个节点共同组成一个复制组&#xff0c;一个事务的提交&#xff0c;必须经过…

Babylonjs学习必备

基于babylonjs封装的一些功能和插件 &#xff0c;希望有更多的小伙伴一起玩babylonjs&#xff1b; 欢迎加群&#xff1a;464146715 ​ 官方文档 中文文档 Babylonjs案例分享 ​ ​

kafka生产者2

1.数据可靠 • 0&#xff1a;生产者发送过来的数据&#xff0c;不需要等数据落盘应答。 风险&#xff1a;leader挂了之后&#xff0c;follower还没有收到消息。。。。 • 1&#xff1a;生产者发送过来的数据&#xff0c;Leader收到数据后应答。 风险&#xff1a;leader应答…

Vision Mamba:使用双向状态空间模型进行高效视觉表示学习

模型效果 将DeiT和Vim模型之间的性能和效率比较&#xff0c;为了进行准确性比较&#xff0c;我们首先在IN1K分类数据集上预训练DeiT和Vim&#xff0c;然后在不同的下游密集预测任务上微调通用主干&#xff0c;即&#xff0c;语义分割、目标检测、实例分割。结果表明&#xff0c…

VIO第5讲:后端优化实践

VIO第5讲后端优化实践&#xff1a;逐行手写求解器 文章目录 VIO第5讲后端优化实践&#xff1a;逐行手写求解器1 非线性最小二乘求解流程1.1 H矩阵不满秩的解决办法1.2 H矩阵的构建1.2.1 确定维度1.2.2 构建海塞矩阵 1.3 初始化μ—LM算法1.4 求解线性方程1.4.1 非SLAM问题—求逆…

【架构】GPU架构总结

文章目录 GPU架构GPU渲染内存架构Streaming Multiprocessor(SM)CUDA CoreTensor CoreRT CoreCPU-GPU异构系统GPU资源管理模型 GPU架构演进G80 架构Fermi 架构Maxwell架构Tesla架构Pascal架构Volta 架构Turing架构Ampere 架构Hopper架构 参考文献 GPU架构 主要组成包括&#xf…

【C语言】指针初阶

正文开始之前&#xff0c;我们要记住一个东西就是&#xff1a;地址指针 目录 一、指针的解释二、指针变量和地址1、取地址操作符2、指针变量和解引用操作1、指针变量2、拆解指针类型3、解引用操作符4、注意事项 3、指针变量的大小4、指针的解引用5、void*指针 三、指针的运算1、…

【Java程序设计】【C00277】基于Springboot的招生管理系统(有论文)

基于Springboot的招生管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的招生管理系统 本系统分为系统功能模块、管理员功能模块以及学生功能模块。 系统功能模块&#xff1a;在系统首页可以查看首页、专业…

Linux——静态库

Linux——静态库 静态库分析一下 ar指令生成静态库静态库的使用第三方库优化一下 gcc -I(大写的i) -L -l(小写的l)&#xff0c;头文件搜索路径&#xff0c;库文件搜索路径&#xff0c;连接库 今天我们来学习静态库的基本知识。 静态库 在了解静态库之前&#xff0c;我们首先来…

【Linux】MySQL数据库的使用

【Linux】MySQL数据库的使用 一、访问MySQL数据库二、创建及删除库和表1、创建新的库2、创建新的表3、删除一个数据表4、删除一个数据库 三、管理表中的数据记录1、插入数据记录2、查询数据记录3、修改数据记录4、删除数据记录 四、数据库用户授权1、授予权限2、查看权限3、撤销…

C/C++暴力/枚举/穷举题目持续更新(刷蓝桥杯基础题的进!)

目录 前言 一、百钱买百鸡 二、百元兑钞 三、门牌号码&#xff08;蓝桥杯真题&#xff09; 四、相乘&#xff08;蓝桥杯真题&#xff09; 五、卡片拼数字&#xff08;蓝桥杯真题&#xff09; 六、货物摆放&#xff08;蓝桥杯真题&#xff09; 七、最短路径&#xff08;蓝…