class Solution {
public:
/*
dp[i]:将i拆分后的正整数相乘得到的最大值
初始化应该是初始化dp[2]=1;因为初始化dp[0],dp[1]没有意义
index 0 1 2 3 4 5 6 7 8 9 10
dp # # 1 2 4 6 9 12 18 27 36
dp[i]只能来自于
1.j*(i-j)或者
2.dp[j]*(i-j)或者
3.j*dp[i-j]或者
4.dp[j]*dp[i-j]
将2,3归为一种遍历情况,有数学公式证明拆分成4个以上的数相乘一定是最小的,可以不用比较,
通过每种情况推导出dp[i],然后取最大的一种情况,所以推导公式:
dp[i]=max(dp[i],max(dp[j]*(i-j),j*(i-j)));
*/
int integerBreak(int n) {
vector<int>dp(n+1);
dp[2]=1;
for(int i=3;i<=n;i++){
for(int j=1;j<=i-2;j++){//注意这里的退出条件因为dp[0],dp[1]是没有意义的,默认为0,所以写j<=i-2就行,写成j<=i-1也行,因为他要求的是最大值,遍历到dp[1]也无所谓
dp[i]=max(dp[i],max(dp[j]*(i-j),j*(i-j)));
}
}
return dp[n];
}
};
class Solution {
public:
/*
假设n个节点的不同二叉树搜索树有G(n)个,令f(i):i为节点的二叉树的个数;
G(n)=f(1)+f(2)+f(3)+...+f(n);
f(i)=G(i-1)*G(n-i);
所以整理得:
G(n)=G(0)*G(n-1)+G(1)*G(n-2)+G(2)*G(n-3)+...G(n-2)*G(1)+G(n-1)*G(0);
dp[i]:与G(n)的定义相同;
for(int i=1;i<=n;i++){
for(int j=0;j<=i-1;j++){
dp[i]=dp[i]+dp[j]*dp[i-j-1];
}
}
*/
int numTrees(int n) {
vector<int>dp(n+1);
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=i-1;j++){//左子树的个数从0~i-1,右子树的个数从i-1~0;
dp[i]=dp[i]+dp[j]*dp[i-j-1];
}
}
return dp[n];
}
};