一天一大 leet(从先序遍历还原二叉树)难度:困难 DAY-18
时间:2022-07-25
本文章向大家介绍一天一大 leet(从先序遍历还原二叉树)难度:困难 DAY-18,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目(难度:困难):
我们从二叉树的根节点 root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S,还原树并返回其根节点 root。
示例
- 示例 1
1
/
2 3
/ /
4 5 6 7
输入:"1-2--3--4-5--6--7"
输出:[1,2,5,3,4,6,7]
- 示例 2
1
/
2 5
/ /
3 6
/ /
4 7
输入:"1-2--3---4-5--6---7"
输出:[1,2,5,3,null,6,null,4,null,7]
- 示例 3
1
/
401
/
349 88
/
90
输入:"1-401--349---90--88"
输出:[1,401,null,349,88,90]
提示
- 原始树中的节点数介于 1 和 1000 之间。
- 每个节点的值介于 1 和 10 ^ 9 之间。
抛砖引玉
- 输入一个字符串
- 字符串中n个'-'表示n级
- '---n...---m'表示n和m都是上一级的子集,n是left,m是right,先left后right
- 字符串顺序:一条线所有的子节点+下一条线所有子节点.....
逻辑
- 先取出第一个数组作为树的根节点
- 循环字符串记录'-'的个数,多少个n就记录多少级,根据级数把能得到的树放到数组中
- 记录level和取本层数据的注意事项:
- 数字和'-'切换时重置level和value
- 因为字符串顺序:一条线所有的子节点+下一条线所有子节点.....,以第二层为例:
- 第一条线循环到结束后可能还会在之后一个有level为2的数据,
- 那就可以判断这个level是不是已经有了left、right没有的话就给原树增加新的树节点
- 依次类推,所有后面出现的节点本身都是有依附节点的,最终所有的节点都会追加到起始的根节点
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {string} S
* @return {TreeNode}
*/
var recoverFromPreorder = function (S) {
var level = 0,
value = 0
var _result = [new TreeNode(S.split('-')[0])]
for (let i = 1; i < S.length; i++) {
if (S[i] == '-') {
level++
value = 0
} else if (level > 0) {
value = value * 10 + Number(S[i])
if ((S[i + 1] && S[i + 1] === '-') || i === S.length - 1) {
var nodeTree = new TreeNode(value)
if (_result[level - 1].left == null) {
_result[level - 1].left = nodeTree
} else {
_result[level - 1].right = nodeTree
}
_result[level] = nodeTree
level = 0
}
}
}
return _result[0]
}
其他解法
/**
* @param {number[]} A
* @return {number}
*/
var recoverFromPreorder = function (S) {
const stack = []
for (let i = 0; i < S.length;) {
let curLevel = 0 //一个curNode对应一个curLevel
while (i < S.length && S[i] == '-') { // 避免循环半途中出界
i++
curLevel++ // 连字符个数代表level
}
const start = i // 记录当前节点值的开始位置
while (i < S.length && S[i] != '-') {
i++ // 指针移到当前节点值的结束位置
}
const curNode = new TreeNode(S.slice(start, i)) //创建当前节点
if (stack.length == 0) { // ROOT入栈,不用找父亲,continue
stack.push(curNode)
continue
}
while (stack.length > curLevel) { // 栈顶不是父亲,栈顶出栈
stack.pop() // 直到栈顶是父亲
}
if (stack[stack.length - 1].left) { // 左儿子已存在
stack[stack.length - 1].right = curNode // 安排为右儿子
} else {
stack[stack.length - 1].left = curNode // 安排为左儿子
}
stack.push(curNode) // 节点肯定要入栈一次
}
return stack[0] // 栈底就是根节点
};
- 使用递归,一个层级一次递归
- 使用正则切分除本层的数据和未分离出来的字符串
- 本层数据直接生成树结构
- 未分离的数据根据切位的位置,递归进入left和right
/**
* @param {number[]} A
* @return {number}
*/
var maxScoreSightseeingPair = function (A) {
if (!S) return null
const reg = new RegExp(`(?<=\d)${char}(?=\d)`),
[root, left, right] = S.split(reg),
treeNode = new TreeNode(+root);
treeNode.left = recoverFromPreorder(left, char + '-')
treeNode.right = recoverFromPreorder(right, char + '-')
return treeNode
}
菜鸟的自白
- 开始的思路也是通过正则匹配出来,但是对数据的切分一直错误,才不得不去按部就班的去循环,个人觉得,正则出来起来会更简洁
// 配置 两个数字包含着的层级数[val-left,*-right]
/d-{n}d/g
// 跟 数字 -- 数字 切分字符串
/?<=\d)${char}(?=\d/g
- 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 数组属性和方法
- 关于useState的一切
- 关于useEffect的一切
- (25)Bash数值运算与运算符
- (27)正则表达式
- (28)字符截取命令cut、printf
- (29)字符截取命令awk
- RTSP协议视频平台EasyNVR流媒体服务器音频播放完毕后,视频为什么也会卡住?
- Redis | Redis 有序集合相关命令
- TypeScript 4.0正式发布!现在是开始使用它的最佳时机
- 微服务开源框架TARS 之 基础组件
- Gitlab-ci:从零开始的前端自动化部署
- 从 1 到 0 构建博客项目(导读)
- 应该在JavaScript中使用Class吗
- Go语言小书 | 关于编译和语法
- Go语言小书 | 小试牛刀,从hello world开始