Offer 驾到,掘友接招!我正在参与2022春招系列活动春招打卡任务,点击查看活动详情。
题目介绍
给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树。可以按 任意顺序 返回答案。
示例1
输入:n = 3
输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
示例2
输入: n = 1
输出: [[1]]
提示:
1 <= n <= 8
解题思路
这道题使用 递归 + 排列组合 的方式来求解,我们以一棵 3 个节点的树来进行讲解。
首先,一棵 3 个节点的二叉搜索树分别可以以 1、 2、 3 为根节点进行构建,根据二叉搜索树根节点一定比左节点大同时比右节点大的特点:
- 以
1为根节点。左子树没有任何节点,是[null],右子树的节点为{2, 3},有两种情况[2, null, 3]、[3, 2, null],因此以1为根节点的情况就是左子树和右子树的一种排列组合,数量为2
- 以
2为根节点。因为左子树只有节点1,右子树只有节点3,因此左右子树的排列组合只有一种情况
- 以
3为根节点。因为{1, 2}为左子树的节点,有两种情况[2, 1, null]、[1, null, 2],右子树没有节点,为[null],左右子树的排列组合数量为2
因此以 3 个节点构成的二叉搜索树有 2 + 1 + 2 = 5 种情况。但是题目要求我们给出所有的情况,因此我们可以以当前节点为根节点,计算其左右子树的结构,然后构建一棵树
更多节点构成的二叉搜索树与 3 个节点构成二叉搜索树的情况类似,只是根节点的左右子树的可能结构需要以递归的方式来得出
解题代码
var generateTrees = function(n) {
// n 个节点分别是 1 - n
const ans = dfs(1, n)
return ans
};
var dfs = function(l, r) {
const ans = []
// 说明当前的树不存在,没有节点,返回 null
if (l > r) {
ans.push(null)
return ans
}
for (let i = l; i <= r; i++) {
// 获得构成左子树的所有情况
const left_tree = dfs(l, i - 1)
// 获得构成右子树的所有情况
const right_tree = dfs(i + 1, r)
// 当前树的所有情况就是左子树和右子树之间的排列组合
for (const left of left_tree) {
for (const right of right_tree) {
// 构建以当前节点为根节点,左子树和右子树随机组合的树
ans.push(new TreeNode(i, left, right))
}
}
}
// 返回当前树的所有构建情况
return ans
}