【LeetCode】重建二叉树day04
时间:2022-07-23
本文章向大家介绍【LeetCode】重建二叉树day04,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7
限制:
0 <= 节点个数 <= 5000
解题思路
- 二叉树的特点是什么?
- 每个节点最多有两棵子树,所以二叉树中不存在度大于2的节点。也可以没有左子树和右子树。
2.根据便利的特点来进行重建
- 前序遍历: 二叉树为空,则空操作返回,否则访问根节点,然后前序遍历左子树,再前序遍历右子树。这块就得注意了这就是插入点。
- 中序便利: 若树为空,则空操作返回,否则从根节点开始,中序遍历根节点的左子树,然后访问根节点,然后访问右子树。
3.通过回想这个两个遍历的特点,那开始重建
4.从中序便利中我们可以判断出根节点是哪一个,那就是前序遍历的preorder[0].
5.我们知道了根节点,哪我们可以根据中续遍历,就可以得出左子树和右子树。有哪些元素。
6.由于树中的节点数量与遍历方式无关,通过中序遍历得知左子树和右子树的节点数量之后,可以根据节点数量得到前序遍历中的左子树和右子树的分界,因此可以进一步得到左子树和右子树各自的前序遍历和中序遍历,可以通过递归的方式,重建左子树和右子树,然后重建整个二叉树。
代码
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
//如果前序遍历数组为空那这棵树也是空的
if(preorder == null ){
return null ;
}else{
//先拿到中序便利的数量
int length = inorder.length;
//通过Map记录中序遍历的值,在后面可以根据根节点拿到左子树和又字树的元素
Map<Integer,Integer> inorderMap = new HashMap<Integer,Integer>();
for(int i = 0 ;i<length;i++){
inorderMap.put(inorder[i],i);
}
// 构建一个树根据前序遍历和后续遍历的数组
//其实有人会问为什么要这样写这么多参数。因为我们要递归调用将其中的遍历的数组切开,然后去便利左子树右子树。
return buildTree(preorder,0,length-1,inorder,0,length-1,inorderMap);
}
}
public TreeNode buildTree(int [] preorder,int preorderStart,int preorderEnd,int[] inorder,int inoderStart, int inorderEnd,Map<Integer,Integer> inorderMap){
if(preorderStart>preorderEnd){
return null;
}
// 拿到根节点
int rootVal = preorder[preorderStart];
// 创建一颗有根节点的二叉树
TreeNode root = new TreeNode(rootVal);
if(preorderStart == preorderEnd){
return root;
}else{
拿到根节点在遍历数组中的位置
int rootIndex = inorderMap.get(rootVal);
// 左子树的节点数量
int leftNodes = rootIndex - inoderStart; 右子树节点的数量
int rightNodes = inorderEnd - rootIndex;
构建左子树
TreeNode leftSubtree = buildTree(preorder, preorderStart + 1, preorderStart + leftNodes, inorder, inoderStart, rootIndex - 1, inorderMap);
便利右子树
TreeNode rightSubtree = buildTree(preorder, preorderEnd - rightNodes + 1, preorderEnd, inorder, rootIndex + 1, inorderEnd, inorderMap);
//将左子树与右子树拼起来
root.left = leftSubtree;
root.right = rightSubtree;
}
return root;
}
}
总结
- 刚开始做这道题真的没有思路,于是就看一边答案,然后尝试自己慢慢去写,然后几经调试。就跑出来了。
- 核心思想就是中序遍历和前序遍历的算法。
- 还有就是理解左子树和右子树的便利过程
参考
- https://blog.csdn.net/My_Jobs/article/details/43451187
- https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/
- mmc如何管理本机上的(数字/x.509)证书
- Jquery $.extend的重载方法详述
- Jquery ajax调用后台aspx后台文件方法(不是ashx)
- [原创]x.509证书在WCF中的应用(CS篇)
- tomcat
- 快速入门系列--WebAPI--01基础
- 分析程序员到底是不是吃青春饭
- Jquery dom搜索之siblings()方法
- 汽车黑科技!想想以后不是我们亲自驾驶汽车还是蛮开心的
- 快速入门系列--CLR--02多线程
- JavaScript之将JS代码放在什么位置最合适
- 快速入门系列--TSQL-01基础概念
- 初识javascript
- [原创]x.509证书在WCF中的应用(Web/IIS篇)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python+selenium 自动化-启用带插件的chrome浏览器,调用浏览器带插件,浏览器加载配置信息。
- Java并发编程(4)- 线程安全策略
- Java并发编程(3)- 如何安全发布对象
- Python 技术篇-3行代码实现语音朗读,pywin32库实现语音朗读
- Java并发编程(2)- 线程安全性详解
- Python 技术篇-1行代码实现语音识别,speech库快速实现简单的语音对话
- linux和windows互传文件,用户配置文件和密码配置文件,用户组和用户管理
- 除Innodb和MyISAM外MySQL还有哪些存储引擎
- MySQL自身对性能的影响
- Python 技术篇-用pywin32库实现读写剪贴板
- Excel 技巧篇-在指定范围内生成指定小数位的随机数
- PyQt5 技巧篇-窗口置顶设置,如何使窗口始终显示在最前面
- 解决npm install时报错无法安装chromedriver的问题
- 解决集成jpa时无法创建entityManagerFactory的问题
- Spring船新版推出的WebFlux,是兄弟就来学我