菜鸡每日一题系列打卡96天
每天一道算法题目
小伙伴们一起留言打卡
坚持就是胜利,我们一起努力!
题目描述(引自LeetCode)
给定一个整数n,求以1 ... n为节点组成的二叉搜索树有多少种?
示例:
输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
题目分析
这是上一道题目的简化版,我们在上一题中提到了卡特兰数的概念,这道题目其实就是求取的卡特兰数,但为了提供更多思路,菜鸡将采取两种方式进行求解。
第一种是我们经常使用的动态规划。
首先,我们记以i(1 <= i <= n)为根的二叉搜索树为F(i, n),记二叉搜索树的总数为G(n),则
而考虑以i为根的二叉搜索树,其左子树必定以j(1 <= j < i)为根,其右子树必定以k(i < k <= n)为根。因此,以i为根的二叉搜索树,其左子树的总数为G(i - 1),其右子树的总数为G(n - i)。从而有
综合上述两条等式,我们可以得到
因此,只需要以dp[]数组记录G的值并进行计算即可。
第二种是上文提到的卡特兰数计算。
其实,这种方法可以由动态规划的递推式推演而来,我们可以得到,对n > 0,有
从而可以直接按照上述公式进行计算,得到结果。
代码实现
// 动态规划
class Solution {
public int numTrees(int n) {
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
}
// 卡特兰数
class Solution {
public int numTrees(int n) {
long catalan = 1L;
for (int i = 0; i < n; i++) catalan = catalan * 2 * (2 * i + 1) / (i + 2);
return (int) catalan;
}
}
代码分析
对代码进行分析,动态规划的时间复杂度为O(n^2),空间复杂度为O(n);卡特兰数公式的时间复杂度为O(n),空间复杂度为O(1)。
执行结果
动态规划的执行结果
卡特兰数的执行结果
学习 | 工作 | 分享
????长按关注“有理想的菜鸡”
只有你想不到,没有你学不到