dp[i]
表示数字i
拆分后的最大乘积- 初始化条件,0和1拆分乘积最大为0,2拆分最大乘积为 1
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
,选择当前拆分结果,拆分为两个数的乘积,i - j
的拆分后的最大值与j
的乘积,三个数中的最大值。- 由于每次递推都要用到前面的值,所以遍历顺序从前往后
class Solution {
public:
int integerBreak(int n) {
vector<int> dp(n + 1);
dp[2] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j < i + 1; ++j) {
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}
return dp[n];
}
};
贪心:数学方法求解
每次拆成n个3,如果剩下小于4,则保留,然后相乘
class Solution {
public:
int integerBreak(int n) {
if (n == 2) return 1;
if (n == 3) return 2;
if (n == 4) return 4;
int result = 1;
while (n > 4) {
result *= 3;
n -= 3;
}
result *= n;
return result;
}
};
dp[i]
表示以i
为根节点的二叉搜索树的种类数dp[i] += dp[j - 1] * dp[i - j];
,每棵树可以由其左右子树的排布方式递推而来- 初始化
dp[0] = 1;
空树的排布方式只有一种- 从结点少的情况开始递推
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n + 1);
dp[0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
};