思路
个人的一些思考:
看完别人提供给的解题思路,对这道题目自己一开始的想法是,把所有的BST树的组合统计出来,而看到下面的解法,感觉并没有利用到题目中提到的BST的特性,主要是通过卡特兰数公式进行了求解
参考自灵魂画手的题解
下面是自己关于上述的解释
过程:
1、要获得以当前值为根节点的二叉树个数,如果知道了左子树和右子树的二叉树种类数 ,那我当前的结果只需要把左右子树的二叉树种类相乘即可。
因此,假设函数** f(i)** 表示以节点n为根的二叉搜索树的个数。
2、为了表达f(),我们需要定义n个节点拥有二叉搜索树的个数的函数,因此,假设这个函数为G(n),则可以知道G(n) = f(1)+f(2)+…+f(n),即等于以任何一个节点为根节点的二叉搜索树的个数和。
3、同样的,当i为根节点时,我们可以推导到,左子树节点个数为i-1个,则其拥有二叉搜索树的个数为G(i-1)右子树节点个数为n-i,则其拥有二叉搜索树的个数为G(n-i)。则以i为根节点的二叉搜索树的个数为f(i) = 左子树的二叉树的种类数目 * 右子树的二叉树的种类数目,即f(i) = G(i-1)*G(n-i)
4、可以发现这个转移方程是两步进行的,合并可以得到关于G的最终的动态转移方程
G(n) = G(0)G(n-1)+G(1)G(n-1)+G(2)G(n-2)…+G(n-1)G(0);
该公式称之为卡特兰数
而初始值为dp[0]=0,dp[1]=1。
5、因此,实现代码需要对长度为n的数组的每一个节点进行遍历,使其为根节点,其次是遍历子树的长度,合并结果,最终的dp[n]即为我们要求的结果。
代码
class Solution {
public:
int numTrees(int n) {
vector<int> dp(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];
}
};