一天一大 leet(不同的二叉搜索树 II)难度:中等-Day20200721
时间:2022-07-25
本文章向大家介绍一天一大 leet(不同的二叉搜索树 II)难度:中等-Day20200721,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:
给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树。
示例:
输入:3
输出:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
解释:
以上的输出对应以下 5 种不同结构的二叉搜索树:
1 3 3 2 1
/ / /
3 2 1 1 3 2
/ /
2 1 2 3
抛砖引玉
这道题和之前的一道不同的二叉搜索树差不多了,只是之前只需要输出种类数,本题需要输出二叉树
回顾下不同的二叉搜索树那道题中的逻辑:
- 使用指针 i 将数字切分左右分段
- dp[i]存放指针在 i 时存在的所有可能二叉树数量
- 左右二叉树种类数相乘
那将该逻辑向本题靠下试下:
- 对数字分段的逻辑可以沿用
- dp 就不能只存放数量了,需要存放二叉树(其实这个逻辑还是好实现的[TreeNode()])
- 遍历 i 左右的二叉树时就会发现,不仅要多左侧已经生成的二叉树集合做增加节点的操作,还要对右侧做删除节点的操作 统计数量,可以通过公式推导,但返回真实二叉树就需要枚举所有可能
那既然需要计算增加一个节点枚举所有可能的节点,那不如直接尝试用这个逻辑推导:
- 先任取一个元素生成 TreeNode,然后再向这个 TreeNode 不断增加节点
- 返回节点数累加到 n 时所有的可能 TreeNode
追加节点到已存在树,那剩下的问题就是:
- 要怎么存放哪些已经存在的树呢,
- 怎么在原有树的基础上枚举新加入节点带来的二叉树种类
存放的问题:
1. 可以直接推送到要返回的结果数组里面存贮,那么在推送时,就需要是全节点的树;
综合上面的逻辑,用 i 分割了左侧 left,和右侧 right,那这个全节点的树就应该是:
treeLeft - TreeNode(i) - treeRight
(其中 treeLeft、treeRight 均为在指定范围生成新二叉树,不存在追加节点和删除节点的问题)
如果这个范围是 1 到 n,这时逻辑回归了题目的逻辑,递归走起~
递归的逻辑就只剩问题 2 没有解决了:
- 将要插入的元素生成节点
- 循环原有树的集合(通过指定范围递归生成), 将左侧生成的树拼接到新树的 left,右侧拼接到 right
[1,null,2,null,3],在二叉树中应该和[1,2,null,3,null]不是相同的吗?
1 1
/
2 2
/
3 3
上面这两个树在提交时不算两种也不算相同,只有提交第二种才能通过
最后递归的终止条件:
- 设左侧指针为 start,右侧指针为 end,两个指针交错时及 start > end 是递归终止
特殊情况
- n 为 0 时返回[]
实现
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {number} n
* @return {TreeNode[]}
*/
var generateTrees = function (n) {
function buildTree(start, end) {
let _result = []
// 指针交错递归终止
if (start > end) return [null]
// i指针滑动,枚举left和right分段的所有可能
for (let i = start; i <= end; i++) {
// 左侧和右侧生成树的集合 返回为数组
let left = buildTree(start, i - 1)
let right = buildTree(i + 1, end)
// 循环左右两侧的树集合 分别拼接到新树上,并且存储到结果数组中
for (const leftNode of left) {
for (const rightNode of right) {
let node = new TreeNode(i)
node.left = leftNode
node.right = rightNode
_result.push(node)
}
}
}
// 返回指定范围生成的树集合
return _result
}
// n 为 0 是返回[]
if (n === 0) return []
// 指定最大范围
return buildTree(1, n)
}
优化
- 在 i 滑动时分段也会发生变化,则递归时会有计算过的片段再次计算
- 可以声明一个容器记录已经计算过的判断,再次需要该判断时直接读取
/**
* @param {number} n
* @return {TreeNode[]}
*/
var generateTrees = function (n) {
let map = new Map()
function buildTree(start, end) {
let _result = []
if (start > end) return [null]
// 如果已经计算过则直接返回结果
if (map.has(start + '->' + end)) return map.get(start + '->' + end)
for (let i = start; i <= end; i++) {
let left = buildTree(start, i - 1)
let right = buildTree(i + 1, end)
for (const leftNode of left) {
for (const rightNode of right) {
let node = new TreeNode(i)
node.left = leftNode
node.right = rightNode
_result.push(node)
}
}
}
// 存储计算结果
map.set(start + '->' + end, _result)
return _result
}
if (n === 0) return []
return buildTree(1, n)
}
- 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 数组属性和方法
- vue.js如何快速入门第1篇
- 3.列表-HTML基础
- 启动时间的一些分析
- 1.HTML基础知识-HTML进阶
- 浅析一个postgresql的死锁问题
- 你的第一个React App (二 ) - 应用组件开发
- 在Angular应用里使用Redux
- Elasticsearch 日志配置详解
- Cypress系列(52)- fixture() 命令详解
- Docker学习笔记---Dockerfile
- Java面试高频知识点汇总 JVM专题
- Java面试高频知识点汇总 网络协议专题
- 「Mysql优化大师一」mysql服务性能剖析工具
- FPGA设计心得(12)如何正确使用 in_system_ibert ?
- Java面试高频知识点汇总 垃圾回收(GC)机制专题