96. 不同的二叉搜索树
By Jalan
文章目录
知识工具需求
数据结构和算法
- DP
题解
第一次
思路
BST的中序根结点会把序列分成两个单调的段.然后每个段的根结点又会把这个段分成两个单调的段.
公式可以写作:
T
(
n
)
=
T
(
0
)
∗
T
(
n
−
1
)
+
T
(
1
)
∗
T
(
n
−
2
)
+
T
(
3
)
∗
T
(
n
−
3
)
+
⋯
+
T
(
n
−
1
)
∗
T
(
0
)
(1)
T(n)=T(0)*T(n-1)+T(1)*T(n-2)+T(3)*T(n-3)+\cdots +T(n-1)*T(0) \tag{1}
T(n)=T(0)∗T(n−1)+T(1)∗T(n−2)+T(3)∗T(n−3)+⋯+T(n−1)∗T(0)(1)
这里我们研究T在较小时的表现
分别得出
1 1 2 5 14 42等值.
这时我们有两个选择
- 按(1)公式从3开始推到n的值,使用一个数组保持 T 1 − T n T_1-T_n T1−Tn的n个数,这个就是传统DP
- 非常幸运的,我们看到了一个非常熟悉的序列1 1 2 5 14 42,知道这个是catalan数我们由公式直接计算它
C a t a l a n ( n ) = ( 2 n ) ! n ! ∗ ( n + 1 ) ! Catalan(n)=\frac{(2n)!}{n!*(n+1)!} Catalan(n)=n!∗(n+1)!(2n)!
Catalan数详解
递 归 定 义 f n = f 0 ∗ f n − 1 + f 1 ∗ f n − 2 + … + f n − 1 f 0 , 其 中 n ≥ 2 递 推 关 系 f n = 4 n − 2 n + 1 f n − 1 通 项 公 式 f n = 1 n + 1 C n 2 n 经 化 简 后 可 得 f n = C 2 n n + C 2 n n − 1 只 要 我 们 在 解 决 问 题 时 得 到 了 上 面 的 一 个 关 系 , 那 么 你 就 已 经 解 决 了 这 个 问 题 , 因 为 他 们 都 是 卡 特 兰 数 列 递归定义\\ f_n=f_0∗f_{n-1}+f_1∗f_{n−2}+…+f_{n−1}f_0,其中n≥2\\ 递推关系\\ f_n=\frac{4n−2}{n+1}f_{n−1}\\ 通项公式\\ fn=\frac{1}{n+1}C_n^{2n}\\ 经化简后可得\\ fn=C_{2n}^{n}+C_{2n}^{n-1}\\ 只要我们在解决问题时得到了上面的一个关系,那么你就已经解决了这个问题,因为他们都是卡特兰数列 递归定义fn=f0∗fn−1+f1∗fn−2+…+fn−1f0,其中n≥2递推关系fn=n+14n−2fn−1通项公式fn=n+11Cn2n经化简后可得fn=C2nn+C2nn−1只要我们在解决问题时得到了上面的一个关系,那么你就已经解决了这个问题,因为他们都是卡特兰数列
这里我选择的是使用通项公式计算.但是这个计算不能简单的使用int/double/long long unsigned int做统计,因为都会超范围(阶乘),double不会超,但是误差会大于1;所以这里需要做同步乘除防止超范围.
预期时间复杂度
O(1)
代码
CPP
class Solution
{
public:
int numTrees(int n)
{
int i = n + 1;
int j = 2;
double sum = 1;
while (i <= 2 * n && j <= n + 1)
{
if (i <= 2 * n)
{
sum *= i++;
}
if (j <= n + 1)
{
sum /= j++;
}
}
return sum;
}
};
运行用时
参考文献
结尾
看在我写了这么多注释的份上可以给我点个赞嘛,求求惹=]砰砰砰,给我加点写下去的油呀
@.@
也欢迎关注我的CSDN账号呀=]
**开心code每一天**