《剑指offer》第六天:重建二叉树
时间:2022-07-23
本文章向大家介绍《剑指offer》第六天:重建二叉树,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
❝恶魔:说出你的三个愿望! 男:请你实现我的第二个愿望。 恶魔:然后呢? 男:请你实现我的第一个愿望。 恶魔:Exception in thread "main" java.lang.StackOverflowError —— 小浩 ❞
重建二叉树
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8}
和中序遍历序列 {4,7,2,1,5,3,8,6}
,则重建二叉树并返回。
原题题目
思路分析
动图展示
原文参考
解法
在二叉树的前序遍历序列中,第一个数字总是根结点的值。在中序遍历序列中,根结点的值在序列的中间,左子树的结点位于根结点左侧,而右子树的结点位于根结点值的右侧。
遍历中序序列,找到根结点,递归构建左子树与右子树。
注意添加特殊情况的 if
判断。
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
/**
* 重建二叉树
*
* @param pre 先序序列
* @param in 中序序列
* @return 二叉树根结点
*/
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
if (pre == null || in == null || pre.length != in.length) {
return null;
}
int n = pre.length;
return constructBinaryTree(pre, 0, n - 1, in, 0, n - 1);
}
private TreeNode constructBinaryTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) {
TreeNode node = new TreeNode(pre[startPre]);
if (startPre == endPre) {
if (startIn == endIn) {
return node;
}
throw new IllegalArgumentException("Invalid input!");
}
int inOrder = startIn;
while (in[inOrder] != pre[startPre]) {
++inOrder;
if (inOrder > endIn) {
new IllegalArgumentException("Invalid input!");
}
}
int len = inOrder - startIn;
if (len > 0) {
// 递归构建左子树
node.left = constructBinaryTree(pre, startPre + 1, startPre + len, in, startIn, inOrder - 1);
}
if (inOrder < endIn) {
// 递归构建右子树
node.right = constructBinaryTree(pre, startPre + len + 1, endPre, in, inOrder + 1, endIn);
}
return node;
}
}
测试用例
- 普通二叉树(完全二叉树;不完全二叉树);
- 特殊二叉树(所有结点都没有左/右子结点;只有一个结点的二叉树);
- 特殊输入测试(二叉树根结点为空;输入的前序序列和中序序列不匹配)。
我把我写的所有题解整理成了一本电子书放在了 github 上,三天内冲击到 github 排行榜榜首!近 5w 人下载阅读!要获取的话,直接进入下方链接就可以了(记得给我点个 star):
https://github.com/geekxh/hello-algorithm
- 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 数组属性和方法
- Zabbix MTR 链路质量检测 主备链路监控
- R语言入门之t检验(t test)
- R语言入门之饼图
- 加速Spark编译
- 自定义方便kubectl中pods的管理
- R语言入门之切尾均值(trimmed mean)与绝对中位差(median absolute deviation,mad)
- 盘一盘 Python 特别篇 20 - SciPy 稀疏矩阵
- Spark 3.0.0-SNAPSHOT Access Kerberized HDFS
- Spark Nightly Builds
- R语言入门之基本统计量
- K8S 生态周报| Istio 已修复导致 Pod 崩溃的 bug
- Spark Kubernetes 的源码分析系列 - submit
- 如何交互可视化 Roam Research 局部笔记网络?
- Spark Kubernetes 的源码分析系列 - features
- Spark Kubernetes 的源码分析系列 - scheduler