0x00 题目

给你一个整数 ​​n​​​ ,请你生成并返回
所有由 ​​​n​​​ 个节点组成
且节点值从 ​​​1​​​ 到 ​​n​​​ 互不相同的
不同二叉 ​​​搜索​​​ 树,可以按 ​​任意顺序​​ 返回答案


0x01 思路

二叉搜索树的特征是
​​​根​​​ 节点的值
​​​大于​​​ ​​左​​​ 子树所有节点的值
​​​小于​​​ ​​右​​​ 子树所有节点的值
且 ​​​左​​​ 子树和 ​​右​​​ 子树也同样为二叉 ​​搜索​​ 树

在生成所有可行的二叉 ​​搜索​​​ 树的时候
假设当前序列长度为 ​​​n​​​ 如果枚举根节点的值为 ​​i​​ 那么根据二叉 ​​搜索​​ 树的性质可以知道
​左​​ 子树的节点值的集合为 ​​[1 … i−1]​​​​右​​ 子树的节点值的集合为 ​​[i+1 … n]​

而 ​​左​​​ 子树和 ​​右​​​ 子树的生成
相较于原问题
是一个序列长度 ​​​缩小​​​ 的 ​​子​​​ 问题
因此可以用 ​​​回溯​​ 的方法来解决这道题目

定义 ​​generateTrees(start, end)​​​ 函数
表示当前值的集合为 ​​​[start,end]​​​ 返回序列 ​​[start,end]​​ 生成的所有可行的二叉 ​​搜索​​ 树

按照上面的思路
考虑枚举 ​​​[start,end]​​​ 中的值 ​​i​​​ 为当前二叉搜索树的根
那么序列划分为了 ​​​[start, i−1]​​​ 和 ​​[i+1, end]​​ 两部分

递归调用这两部分
即 ​​​generateTrees(start, i - 1)​​​ 和 ​​generateTrees(i + 1, end)​​​ 获得所有可行的 ​​左​​ 子树和可行的 ​​右​​ 子树
那么最后一步
只要从可行 ​​左​​ 子树集合中选一棵
再从可行 ​​右​​ 子树集合中选一棵
拼接到 ​​根​​ 节点上
并将生成的二叉搜索树放入答案数组即可


0x02 解法

语言:​​Swift​

树节点:​​TreeNode​

public class TreeNode {
public var val: Int
public var left: TreeNode?
public var right: TreeNode?
public init() { self.val = 0; self.left = nil; self.right = nil; }
public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
self.val = val
self.left = left
self.right = right
}
}

解法:

func generateTrees(_ n: Int) -> [TreeNode?] {
// 为 0 时,返回一个空数组
if n == 0 {
return []
}

// 生成序列 [start,end] 的所有可行的二叉 搜索 树
func generateTrees(_ start: Int, _ end: Int) -> [TreeNode?] {
if start > end { return [nil] }
var trees: [TreeNode?] = []

// 依次枚举
for i in start...end {
// 递归生成 左子树集合
let leftTrees = generateTrees(start, i - 1)
// 递归生成 右子树集合
let rightTrees = generateTrees(i + 1, end)

// 从 `左` 子树集合中选一棵
for left in leftTrees {
// 从 `右` 子树集合中选一棵
for right in rightTrees {
// 生成新的二叉搜索树
let cur = TreeNode(i)
cur.left = left
cur.right = right

// 放入结果集
trees.append(cur)
}
}
}

// 最终结果
return trees
}

return generateTrees(1, n)
}

小编辑器