一、概念
1. 什么是二叉搜索树?
二叉搜索树又叫做二叉查找树,二叉排序树,每个节点有两个子节点。
2. 二叉搜索树的特点是什么?
特点是根节点的值大于左子树的值,根节点的值小于右子树的值,左右子树也满足同样性质,注意大小的比较都是为非空的时候
3. 二叉搜索树有哪些应用场景?
在特定的检索条件下,检索效率高。
二、题目
三、解题
1. 思路分析
- 在不懂各种方法的时候,从结果倒推,返回的是一颗有n个节点的二叉搜索树
- 满足二叉搜索树的性质
- 定义一个根节点的值 i 满足输入结果 n 中,那么这个根节点的左子树的节点满足 [1, i - 1],右子树的节点满足 [i + 1, n],同理这个左子树和右子树一样满足以上条件,可以看出是一个递归。
- 那么找到递归的出口 当n<1的时候 返回空。
- 定义一个生成树的函数 generateTree(start, end) 可以生成出满足条件的左子树和右子树,拿着左子树的一个值,拼接上一个右子树的值,拼上根节点就是一个完整的二叉搜索树。
- 同时如果start > end的时候返回空
2. 代码输出
// 树的定义
function TreeNode(val, left, right) {
this.val = (val===undefined ? 0 : val)
this.left = (left===undefined ? null : left)
this.right = (right===undefined ? null : right)
}
function generateTreeList(n){
// 递归的出口
if(n < 1) return []
return generateTree(1, n)
}
function generateTree(start, end){
// 定义treelist
let treeList = []
// 如果左边 > 右边拼接上null
if(start > end) {
treeList.push(null)
}
// 循环开启,从start 到end结束
for (let i = start; i <= end; i++ ){
// 可以得到左子树的集合
let left = generateTree(start, i - 1)
let right = generateTree(i + 1, end)
// 抽取左子树和右子树的点拼接根节点
for(let l of left){
for(let r of right){
const tree = new TreeNode(i)
tree.left = l
tree.right = r
// 拼接到结果
treeList.push(tree)
}
}
}
return treeList
}
3. 思路回顾
- 要根据性质来整理条件 左节点 < 根节点 < 右节点
- 要能找到相同的条件,知道什么时候用递归,什么时候用其它。
- 有时候难理解的是为什么要循环,其实想想树的遍历基本上怎么都要循环树,无非就是循环的时候会做一些额外的事情。