「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
题目
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例1
输入:n = 3
输出:5
示例2
输入:n = 1
输出:1
思路
如果不理解什么是 二叉搜索树,这道题压根就没法解,先复习一下:
首先 二叉树 的概念为:每一个节点都拥有左右两个节点;而 二叉搜索树,还需要满足另外一个条件,就是所有的左节点的数字都比父节点的数字小,右节点的数字都比父节点的数字大。
那么如何去构建一颗 二叉搜索树 呢?比如,对于数字序列 [1, 2, 3],如果将 1 作为根节点,则左子树应该为空,因为找不到比 1 还小的数字了,同时剩下的 [2, 3] 则成为右子树;那么由 [2, 3] 构成的右子树同样也必须是 二叉搜索树,则可以由 2 作为根节点,3 则是右节点;或由 3 作为根节点,则 2 成为左节点。同样的情况,可以依次以 2, 3 作为第一次的根节点,分别去构建 二叉搜索树;
其实上述的例子,就是三个有序的数字,能形成的二叉树的总数;注意这三个有序数字,并不特指 [1, 2, 3],只要是有序的三个数,能够生成的 二叉搜索树 的总数情况都是一样的。
那么可以用 动态规划 解决这道题:
-
定义
dp[i]为i个有序数字,能形成的二叉搜索树的数量 -
则有
dp[0] = 1; dp[1] = 1,即空树也算一个二叉搜索树,当只有一个数字时,也只能形成一种树
对于递归公式,从上面的例子 [1, 2, 3],可以发现 dp[3] 会等于分别以 1, 2, 3 为根节点形成的 二叉搜索树 的数量相加;那么对于两个有序的数字 [2, 3],即 dp[2], 会等于分别以 2, 3 为根节点形成的 二叉搜索树 的数量相加,同时我们有 dp[0] = 1, dp[1] = 1;
动态规划完整代码
/**
* @param {number} n
* @return {number}
*/
var numTrees = function (n) {
const dp = new Array(n + 1).fill(0);
dp[0] = 1;
dp[1] = 1;
// 计算 i 个有序数字形成的 二叉搜索树的数量
for(let i = 2; i <= n; i++) {
// 计算以 j 为根节点,形成的二叉搜索树
for(let j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
};
小结
Get 新知识,什么是 二叉搜索树,如何基于一个有序数列,去构建 二叉搜索树!
知识在于积累,总有用上的那一天。
LeetCode 👉 HOT 100 👉 不同的二叉搜索树 - 中等题 ✅
合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍
如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄