动态规划
// 动态规划 时间 O(n^2), 空间 O(n)
// 1. 1 ... i-1 作为左子树
// 2. i+1 ... n 作为右子树
// 3. 递归构建,由于根值不同,每颗二叉搜索树唯一
// 4. dp[n] : 长度为 n 的序列能构成不同二叉搜索树的个数
// 5. F[i, n] : 以 i 为根、序列长度为 n 的不同二叉搜索树个数(1 <= i <= n)
// 6. 确定状态转移:dp[i] += dp[j-1] * dp[i-j];
// 7. base case : dp[0] = 1, dp[1] = 1;
class Solution {
public:
int numTrees(int n) {
int dp[n+1];
memset(dp, 0, sizeof(dp));
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];
}
};
数学
// 卡特兰数 时间 O(n) 空间 O(1)
// 定义 : C0 = 1, Cn+1 = (2(2n+1))/ (n+2) Cn
class Solution {
public:
int numTrees(int n) {
long long C = 1;
for (int i = 0; i < n; ++i) {
C = C * 2 * (2 * i + 1) / (i + 2);
}
return C;
}
};