343. 整数拆分
一切尽在注释中~
class Solution {
public:
// 动态规划
int integerBreak(int n) {
vector<int> dp(n + 1);
dp[2] = 1;
for (int i = 3; i <= n ; i++) {
// 拆分一个数n 使之乘积最大,那么一定是拆分成m个近似相同的子数相乘才是最大的
// 可以明确的是m一定大于等于2,既然m大于等于2,也就是 最差也应该是拆成两个相同的 可能是最大值。
// 那么 j 遍历,只需要遍历到 n/2 就可以,后面就没有必要遍历了,一定不是最大值。
for (int j = 1; j <= i / 2; j++) {
// 在每次迭代中,通过比较以下两个值来更新 dp[i] :
/* 1. (i - j) * j :这表示两个数字 (i-j) 和 j 的乘积,对应于将 i 分解成两个数字。
2. dp[i - j] * j :这表示将 i-j 分解的最大乘积和 j 的乘积,对应于将 i 分解成多个数字。
通过取上述两个值的最大值,确定了将 i 分解的最大乘积,并将其存储在 dp[i] 中。这个过程对所有从3到 n 的 i 值重复执行,最终, dp[n] 表示将给定的整数 n 分解的最大乘积。 */
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}
return dp[n];
}
};
96.不同的二叉搜索树
class Solution {
public:
// 时间复杂度:$O(n^2)$
// 空间复杂度:$O(n)$
int numTrees(int n) {
vector<int> dp(n + 1);
dp[0] = 1;
for (int i = 1; i <= n; i++) {//这个j表示选择值为j的值作为根节点
//1...i 一共i个节点组成排序二叉树 dp[i] 最终计算到dp[n]
//依次计算以某一个值作为根节点,如 j作为根
//这种情况下,有 dp[j-1]*[i-j]种树;
//把所有的情况相加 可以得到i个数 组成排序二叉树的种类数量 最终计算到dp[n]
for (int j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
};