难度:中等
相关标签:树、二叉搜索树、数学 、动态规划、二叉树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3
输出:5
示例 2:
输入:n = 1
输出:1
提示:
1 <= n <= 19
方法一:
class Solution {
/**
解放一(官方答案):解题思路
标签:动态规划
假设 n 个节点存在二叉排序树的个数是 G (n),令 f(i) 为以 i 为根的二叉搜索树的个数,则
G(n)=f(1)+f(2)+f(3)+f(4)+...+f(n)
当 i 为根节点时,其左子树节点个数为 i-1 个,右子树节点为 n-i,则
f(i) = G(i-1)*G(n-i)
综合两个公式可以得到 卡特兰数 公式
G(n) = G(0)*G(n-1)+G(1)*(n-2)+...+G(n-1)*G(0)
*/
public int numTrees(int n) {
int[] dp = new int[n+1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i < n + 1; i++)
for(int j = 1; j < i + 1; j++)
dp[i] += dp[j-1] * dp[i-j];
return dp[n];
}
}
方法二:递归
class Solution {
static Map<Integer, Integer> map = new HashMap<>();
public int numTrees2(int n) {
//如果只有0,或者1个节点,则可能的子树情况为1种
if (n == 0 || n == 1){
return 1;
}
if (map.containsKey(n)){
return map.get(n);
}
int count = 0;
for (int i = 1; i <= n; i++) {
//当用i这个节点当做根节点时
//左边有多少种子树
int leftNum = numTrees2(i-1);
//右边有多少种子树
int rightNum = numTrees2(n-i);
//乘起来就是当前节点的子树个数
count+=leftNum*rightNum;
}
map.put(n,count);
return count;
}
}