大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。
题目
95. 不同的二叉搜索树 II
给你一个整数 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
思路
- 枚举从
1到n每个元素作为根节点的情况; - 把剩余元素放到子数中去,大于根元素的放到右子树,小于根元素的放到左子树;
- 左右子树一样依次枚举每种可能性,这样子就形成了递归问题;
- 递归问题我们可以找状态转移方程,也就是从从
1到n可以抽离成左边界为1,右边界为n; - 下一轮比如根节点为
3, 那么左子树的两个边界为1和3 - 1,右子树的两个边界为3 + 1和n; - 最终通过两两组合 也就是左子树的所有可能和右子树的所有可能做个双重
for循环枚举即可。
实现
/**
* 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) {
return createNextNode(1, n);
};
// 生成所有的树节点
function createNextNode(left, right) {
if (left === right) return [ new TreeNode(left) ];
let result = [];
// 枚举每个元素作为根节点的情况
for (let i = left; i <= right; i++) {
// 找到所有可能的左右节点的情况
const leftNode = createNextNode(left, i - 1);
const rightNode = createNextNode(i + 1, right);
// 如果没有左节点只有右节点
if (!leftNode.length) {
for (let pr = 0; pr < rightNode.length; pr++) {
const node = new TreeNode(i, null, rightNode[pr]);
result.push(node);
}
}
// 如果没有右节点只有左节点
if (!rightNode.length) {
for (let pl = 0; pl < leftNode.length; pl++) {
const node = new TreeNode(i, leftNode[pl], null);
result.push(node);
}
}
// 枚举所有的可能性
for (let pl = 0; pl < leftNode.length; pl++) {
for (let pr = 0; pr < rightNode.length; pr++) {
const node = new TreeNode(i, leftNode[pl], rightNode[pr]);
result.push(node);
}
}
}
return result;
}
代码简化
/**
* 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) {
return createNextNode(1, n);
};
// 生成所有的树节点
function createNextNode(left, right) {
if (left === right) return [ new TreeNode(left) ];
let result = [];
// 枚举每个元素作为根节点的情况
for (let i = left; i <= right; i++) {
// 找到所有可能的左右节点的情况
const leftNode = createNextNode(left, i - 1);
const rightNode = createNextNode(i + 1, right);
// 如果没有左节点
if (!leftNode.length) {
leftNode.push(null);
}
// 如果没有右节点
if (!rightNode.length) {
rightNode.push(null);
}
// 枚举所有的可能性
for (let pl = 0; pl < leftNode.length; pl++) {
for (let pr = 0; pr < rightNode.length; pr++) {
const node = new TreeNode(i, leftNode[pl], rightNode[pr]);
result.push(node);
}
}
}
return result;
}
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。