leetcode刷题(剑指offer) 105.从前序与中序遍历序列构造二叉树

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

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorderinorder无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

解法:

解题之前先准备好需要的类。一个TreeNode(题目要求),一个TreeNode的工具类(用于层级打印Tree),由于树类型的题,这两个类出现较为频繁,因此,我单独抽出到公共模块中。

TreeNode:


/**
 * @author bwzfy
 * @ClassName TreeNode
 * @create 2024/1/24 - 14:47
 * @Version 1.0
 **/
public class TreeNode {
    public Integer val;

    public TreeNode left;

    public TreeNode right;

    public TreeNode(Integer val) {
        this.val = val;
    }

    public TreeNode(Integer val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

TreeNodeUtils:


import java.util.ArrayDeque;
import java.util.Queue;

/**
 * @author bwzfy
 * @ClassName TreeNodeUtils
 * @create 2024/1/24 - 17:03
 * @Version 1.0
 **/
public class TreeNodeUtils {

    /**
     * 层级打印TreeNode
     * @param root
     */
    public static void levelPrintTreeNode(TreeNode root) {
        Queue<TreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        StringBuilder sb = new StringBuilder("[");
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (node.val == null) {
                sb.append("null, ");
                continue;
            }else {
                sb.append(node.val + ", ");
            }
            if (node.left != null) {
                queue.add(node.left);
            }else {
                queue.add(new TreeNode(null));
            }
            if (node.right != null) {
                queue.add(node.right);
            }else {
                queue.add(new TreeNode(null));
            }
        }
        sb.append("]");
        System.out.println(sb);
    }

}


看到这道题的时候,脑海中第一反应就是递归,递归逻辑即为拿整个先序遍历数组和整个中序遍历数组生成TreeNode

  • 首先根据先序遍历的确定根节点,根节点就是先序遍历数组的第一个元素
  • 随后寻找左子树的所有数据,根据中序遍历数组,遍历整个中序数组,直到寻找到跟节点,那么根节点之前的所有元素,都是左子树的成员,这即是中序数组中构成左子树的所有数据。借此计算出左子树有多少节点假定为n,将先序数组,从根节点开始往后n个元素,这n个元素即为先序数组中构成左子树的所有数据。右子树同理
  • 将上一步获取到的先序数组和中序数组中所有构成左子树的数据和右子树的数据,分别递归。

代码如下:


/**
 * @author bwzfy
 * @ClassName _105从前序与中序遍历序列构造二叉树
 * @create 2024/1/24 - 14:18
 * @Version 1.0
 **/
public class _105从前序与中序遍历序列构造二叉树 {
    public static void main(String[] args) {
        int[] preorder = {3, 9, 20, 15, 7};
        int[] inorder = {9, 3, 15, 20, 7};
        TreeNode treeNode = buildTree(preorder, inorder);
        TreeNodeUtils.levelPrintTreeNode(treeNode);
    }

    public static TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder.length == 0 || inorder.length == 0) {
            return null;
        }
        return buildTreeSolve(preorder, 0, preorder.length, inorder, 0, inorder.length);
    }

    private static TreeNode buildTreeSolve(int[] preorder, int pStart, int pEnd, int[] inorder, int iStart, int iEnd) {
        if (pStart >= pEnd || iStart >= iEnd) {
            return null;
        }
        TreeNode root = new TreeNode(preorder[pStart]);
        if (pEnd - pStart == 1 || iEnd - iStart == 1) {
            return root;
        }
        // 中序遍历找到根节点的位置
        int iRootIndex = 0;
        for (int i = iStart; i < iEnd; i++) {
            if (inorder[i] == preorder[pStart]) {
                iRootIndex = i;
                break;
            }
        }
        int leftNum = iRootIndex - iStart;
        // 递归构造左树
        root.left = buildTreeSolve(preorder, pStart + 1, pStart + leftNum + 1, inorder, iStart, iRootIndex);
        // 递归构造右树
        root.right = buildTreeSolve(preorder, pStart + leftNum + 1, pEnd, inorder, iRootIndex + 1, iEnd);
        return root;
    }
}

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

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

相关文章

JVM实战(34)——内存溢出之消息队列处理不当

一、简介 本章&#xff0c;我们将介绍一个因为处理消息队列中的数据不当而引起的内存溢出问题&#xff0c;先来看下系统的背景。 1.1 系统背景 这是一个线上的数据同步系统&#xff0c;专门从Kafka消费其它系统送进去的数据&#xff0c;处理后存储到自己的数据库中&#xff1…

TensorFlow 深度学习 开发环境搭建 全教程

PyTorch 深度学习 开发环境搭建 全教程 1、指定清华源命令 -i https://pypi.tuna.tsinghua.edu.cn/simple​ 2、conda安装 这是AI开发环境的全家桶&#xff0c;官网下载链接Anaconda | Start Coding Immediately 尽量不要选择太新版本的python&#xff0c;3.8/3.9就已经足…

一次性密码 One Time Password,简称OTP

一次性密码&#xff08;One Time Password&#xff0c;简称OTP&#xff09;&#xff0c;又称“一次性口令”&#xff0c;是指只能使用一次的密码。一次性密码是根据专门算法、每隔60秒生成一个不可预测的随机数字组合&#xff0c;iKEY一次性密码已在金融、电信、网游等领域被广…

如何系统学习机器学习?

要系统学习机器学习&#xff0c;首先需要掌握一些基础编程技能&#xff0c;如Python。其次&#xff0c;学习基础的数学概念&#xff0c;如线性代数、概率论和统计学。然后&#xff0c;选择一些优质的在线课程和教材进行深入学习。最后&#xff0c;通过实践项目来巩固所学知识。…

[极客大挑战 2019]BabySQL1

发现union select被过滤了&#xff0c;双写绕过 or、from被过滤 where被过滤 在b4bysql中找到flag

微信小程序(十五)自定义导航栏

注释很详细&#xff0c;直接上代码 新增内容&#xff1a; 1.组件文件夹创建方法 2.自定义组件的配置方法 3.外部修改组件样式&#xff08;关闭样式隔离或传参&#xff09; 创建组件文件夹 如果是手动创建建议注意在json文件声明&#xff1a; mynav.json {//声明为组件可将这一…

中移(苏州)软件技术有限公司面试问题与解答(4)—— virtio所创建的设备1

接前一篇文章&#xff1a;中移&#xff08;苏州&#xff09;软件技术有限公司面试问题与解答&#xff08;0&#xff09;—— 面试感悟与问题记录 本文参考以下文章&#xff1a; VirtIO实现原理——PCI基础 VirtIO实现原理——virtblk设备初始化 特此致谢&#xff01; 本文对…

vue创建前端项目

背景 项目中需要用到前端技术&#xff0c;通过技术调研和团队分析&#xff0c;则采用vue作为前端主要技术栈。 问题 安装好后vue&#xff0c;按理说就可以创建vue项目 vue init webpack 项目名称 npm install&#xff0c;使用vue-cli脚手架搭建项目卡在sill idealTree buil…

(统计用词)Identifiability可识别性

A researcher can meaningfully discuss the model mathematical properties, estimation of parameters, hypotheses testing about parameters only if the model is said to be identifiable。 这里的model你可理解为就是一个分布&#xff0c;比如正态分布&#xff0c;其有…

宋仕强论道之华强北之胡说八道(五十)

最后又是我宋仕强胡说八道时间了&#xff0c;我经常在华强北一本正经的胡说八道。前段时间刀郎《罗刹海市》这歌很火&#xff0c;后面刀郎唱到了德国哲学家维特根斯坦&#xff0c;维特根斯坦从哲学层面来讲这个世界很多事情是说不清楚的&#xff0c;如我们思考时思路很清晣的事…

前端实现转盘抽奖 - 使用 lucky-canvas 插件

目录 需求背景需求实现实现过程图片示意实现代码 页面效果lucky-canvas 插件官方文档 需求背景 要求实现转盘转动抽奖的功能&#xff1a; 只有正确率大于等于 80% 才可以进行抽奖&#xff1b;“谢谢参与”概率为 90%&#xff0c;“恭喜中奖”概率为 10%&#xff1b; 需求实现 实…

CSDN社区怎么修改社区名称?上传社区logo等信息?

今天看到有人求助CSDN社区中如何修改社区名称以及上传社区logo等社区信息&#xff0c;对于这个问题&#xff0c;刚好boke112百科也创建有一个WordPress社区&#xff0c;所以知道怎么操作&#xff0c;具体如下&#xff1a; 1、前往CSDN社区并登录 >> 在右侧“我的社区”中…

【Java】SpringMVC参数接收(一)

1、接收单个参数 &#xff08;1&#xff09;直接接收参数 RequestMapping("/hello") RestController public class HelloSpring {RequestMapping("/t2")public String t2(String name){return "name" name;} } 当没有传入参数时&#xff0c;返…

IDEA远程服务器开发

IDEA的远程开发是在本地去操远程服务器上的代码&#xff0c;可以直接将本地代码的编译,构建,调试,运行等工作都放在远程服务器上而本地运行一个客户端远程去操作服务器上的代码,就如同我们平常写代码一样。相比于云桌面成本更低,开发效率更高。 1.首先服务器配置jdk&#xff0…

Vue2基础-Vue组件化编程

文章目录 一、模块与组件1、概念2、分类 二、非单文件组件1、创建组件2、注册组件1&#xff09;局部注册2&#xff09;全局注册 3、注意点1&#xff09;组件名2&#xff09;关于组件标签 三、VueComponent1、概念2、内置关系 三、单文件组件1、格式2、引用1&#xff09;暴露2&a…

多场景四向穿梭车系统|HEGERLS托盘四向车是如何实现自动识别存取搬运拣选功能的?

一般来说&#xff0c;物料包装形式可分为托盘和料箱&#xff0c;然而二者在仓储内部物流的作业方式却全然不同。托盘截面较大&#xff0c;则适用于成品搬运&#xff1b;而料箱相对小一些的&#xff0c;则需以原配件、零配件为主。当然所有的物流形式都离不开托盘&#xff0c;工…

Sqlite真空命令VACUUM

之前在项目中使用了sqlite数据库&#xff0c;当日志变大时&#xff0c;执行CRUD操作就会变慢 后来尝试删除7天前的记录进行优化 delete from XX_CollectData where CreateTime<2024-01-24 发现sqlite文件的大小就没有变化&#xff0c;delete命令只是逻辑删除&#xff0c;…

构建库函数雏形(以GPIO为例)

构建库函数雏形 进行外设结构体定义构建置位和复位函数进行库函数的自定义 step I&#xff1a; \textbf{step I&#xff1a;} step I&#xff1a; 对端口进行输出数据类型枚举 step II&#xff1a; \textbf{step II&#xff1a;} step II&#xff1a;对端口进行结构化描述 step…

76.Go分布式ID总览

文章目录 简介一&#xff1a;UUID二、雪花算法三&#xff1a;Leaf-snowflake四&#xff1a;数据库自增ID五&#xff1a;使用Redis实现分布式ID生成六&#xff1a;使用数据库分段&#xff08;Leaf-segment&#xff09;七 &#xff1a;增强版Leaf-segment八&#xff1a;Tinyid九&…

Linux破解密码

破解root密码&#xff08;Linux 7&#xff09; 1、先重启——e 2、Linux 16这一行 末尾加rd.break&#xff08;不要回车&#xff09;中断加载内核 3、再ctrlx启动&#xff0c;进入救援模式 4、mount -o remount&#xff0c;rw /sysroot/——&#xff08;mount挂载 o——opti…