题目链接
参考博文
表示根本不知道什么是卡特兰数,百度的截图
根据动态规划解题步骤慢慢分析
根据题意分析,二叉搜索树不同原因在于。一个数列中的所有元素都可以成为祖先。
于是第一个子问题是每个数都可以作为祖先。我们可以遍历数列。
然后确定一个数为祖先后,剩下n-1个数先分为两拨,而这两拨如何分?左子树节点数从0开始一直到某个临界值时,这样过一遍就是完美了。
于是左子树的子树又可以根据这样的递推关系继续往下面分。
当祖先(根为数值为i时),左子树最大的数为i-1。于是左子树的元素个数可以从0增加到i-1。而右子树的节点个数也可以依次增多。
这里的n=3,不是说的根节点数字为3,而是说的当节点数为3的时候
dp[i]=j 表示当有i的节点时,BST的种类数目。
dp[0]=1
; 没有节点只有一种情况,空树
dp[1]=dp[0]*dp[0]=1
; 只有一个节点也是只有一种情况
int i;
for(int j=0;j1];
}
模拟一下输入3的情况
i | ||||
---|---|---|---|---|
i=1 | dp[1]=dp[0]∗dp[0]” role=”presentation” style=”position: relative;”>dp[1]=dp[0]∗dp[0]dp[1]=dp[0]∗dp[0] | |||
i=2 | dp[2]=dp[1]∗dp[0]” role=”presentation” style=”position: relative;”>dp[2]=dp[1]∗dp[0]dp[2]=dp[1]∗dp[0] | dp[2]=dp[0]∗dp[1]” role=”presentation” style=”position: relative;”>dp[2]=dp[0]∗dp[1]dp[2]=dp[0]∗dp[1] | ||
i=3 | dp[3]=dp[2]∗dp[0]” role=”presentation” style=”position: relative;”>dp[3]=dp[2]∗dp[0]dp[3]=dp[2]∗dp[0] | dp[3]=dp[1]∗dp[1]” role=”presentation” style=”position: relative;”>dp[3]=dp[1]∗dp[1]dp[3]=dp[1]∗dp[1] | dp[3]=dp[0]∗dp[2]” role=”presentation” style=”position: relative;”>dp[3]=dp[0]∗dp[2]dp[3]=dp[0]∗dp[2] |
1. i=1 表示只有一个节点的情况
2. i=2 表示两个节点的情况,这个时候就可以利用case1
中计算出来的结果dp[1]
了。
3. i=3 表示三个节点的情况,这个时候就可以利用case2
中计算出来的结果了。
对应i=3的时候
public class Solution{
public int numTrees(int n){
if(n==0||n==1){
return 1;
}
int []dp=new int[n+1];
//每个数都可以做根节点,相当于有这么多个节点时
for(int i=1;i<=n;i++){
//i为根节点时,左子树从0开始增加
for(int j=0;j1];
}
}
return dp[n];
}
}