Medium
题目描述
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?
示例 1:
输入:n = 3
输出:5
示例 2:
输入:n = 1
输出:1
提示:
1 <= n <= 19
解题思路
这道题是经典的卡特兰数问题。我们需要计算由 1 到 n 组成的不同二叉搜索树的数量。
核心思路
对于 n 个节点的二叉搜索树,我们可以选择任意一个节点 i(1 ≤ i ≤ n)作为根节点:
- 左子树包含节点 1 到 i-1,共 i-1 个节点
- 右子树包含节点 i+1 到 n,共 n-i 个节点
设 G(n) 表示 n 个节点能构成的不同二叉搜索树数量,则有递推关系:
G(n) = G(0)×G(n-1) + G(1)×G(n-2) + ... + G(n-1)×G(0)
解法分析
- 动态规划解法:使用数组存储中间结果,自底向上计算
- 数学公式解法:直接使用卡特兰数公式
C(n) = C(2n,n)/(n+1) - 记忆化递归:递归计算并缓存结果
推荐使用动态规划解法,时间复杂度 O(n²),空间复杂度 O(n),思路清晰易懂。
代码实现
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n + 1, 0);
dp[0] = 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:
def numTrees(self, n: int) -> int:
dp = [0] * (n + 1)
dp[0] = dp[1] = 1
for i in range(2, n + 1):
for j in range(1, i + 1):
dp[i] += dp[j - 1] * dp[i - j]
return dp[n]
public class Solution {
public int NumTrees(int n) {
int[] dp = new int[n + 1];
dp[0] = 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];
}
}
/**
* @param {number} n
* @return {number}
*/
var numTrees = function(n) {
const dp = new Array(n + 1).fill(0);
dp[0] = dp[1] = 1;
for (let i = 2; i <= n; i++) {
for (let j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(n²) - 双重循环计算所有状态 |
| 空间复杂度 | O(n) - 使用数组存储中间结果 |
相关题目
- . Unique Binary Search Trees II (Medium)