第一题是整数拆分https://leetcode.cn/problems/integer-break/description/,根据动规五步曲,确定dp[i]为拆分数字i所能得到的最大乘积,显然看出,dp[i]与拆成的dp[j],dp[i - j]有关,dp[i] = max{dp[i], j * (i - j), j * dp[i - j]},由于本题中dp[0],dp[1]并无实质含义,故只对dp[2]进行初始化,从前向后遍历dp数组,代码如下:
class Solution {
public:
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; j++){
dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]));
}
}
return dp[n];
}
};
第二题是不同的二叉搜索树https://leetcode.cn/problems/unique-binary-search-trees/description/,根据动规五步曲,确定dp[i]为1到i节点组成的不同二叉搜索树数量。dp[i] = 头节点元素为1时的二叉搜索树数量 + 头节点元素为2时的二叉搜索树数量 + ··· + 头节点元素为i时的二叉搜索树的数量。dp[i] += dp[j - 1] * dp[i - j],j - 1为j子树的左子树元素个数,i - j 为j子树的右子树元素个数。dp[0]为0个节点组成的二叉搜索树,即空树,故dp[0] = 1。从前到后遍历dp数组。
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];
}
};