343. 整数拆分
一、做题感受&第一想法
其实第一反应是回溯……但感觉每层的集合都会很繁琐
二、学习文章后收获
1.动态规划思路
-
动规五要素分析
- dp和i的定义:dp[i]指把i拆分后最大乘积(所以dp[1]、dp[0]都没有太大意义,因为0和1拆了乘积也是0)
- 递归公式:
dp[i] = max(j * (i - j) , j * dp[i - j]), 1 <= j < i - 1
(j<i-1是为什么?因为j = i-1时,dp[j-i]也就是dp[1]为0,没有意义;而 j*(i-j)也就是(i-1)*1,这和 j=1重复了,所以可以省去j = i-1的讨论!) - 初始化:dp[0] = 0,dp[1] = 0,dp[2] = 1
- 遍历顺序:从前往后
- 手算序列(略)
-
递归公式的说明:求dp[i]可分成两种情况
- 把 i 拆成 j 和 i - j 两个数,总共两个数。
- 把 i 拆成 j 和"和为 i - j 的若干个数",总共大于等于三个数。
class Solution {
public:
int integerBreak(int n) {
vector<int> dp(n+1,0); //dp[i]:拆分i得到的最大乘积
dp[0] = 0;
dp[1] = 0; //其实这俩初始化无所谓,因为没有意义
dp[2] = 1; // 1*1
for(int i = 3;i <= n;i++){
for(int j = 1;j < i - 1;j++){
dp[i] = max(dp[i],max(j*(i-j),j*dp[i-j]));
}
}
return dp[n];
}
};
2.动态规划优化
思路:for循环上的剪枝,剪枝依据是,要想找到乘积最大的拆分方式,需要让拆出来的所有数字尽可能大小相似。所以,对于太大的 j ,可以直接跳过。
故内层for的条件改为 j <= i/2:for (int j = 1; j <= i / 2; j++)
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 / 2; j++) { //here!
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}
return dp[n];
}
};
2.贪心思路
思路:本题也可以用贪心,每次拆成n个3,如果剩下是4,则保留4,然后相乘,但是这个结论需要数学证明其合理性!
此处没有证明,而是直接用了结论。
说明:
if(n == 2) return 1;
if(n == 3) return 2;
if(n == 4) return 4;
剩下的,拆成3的和,直到剩下4或者不足3(也就是前面是一堆3,最后剩下的值<=4即停止,作为最后一个数字)。
class Solution {
public:
int integerBreak(int n) {
if(n == 1 || n == 0) return 0;
if(n == 2) return 1;
if(n == 3) return 2;
if(n == 4) return 4;
int remains = n - 3,result = 3;
while(remains > 4){
result *= 3;
remains -= 3;
}
result *= remains;
return result;
}
};
三、过程中遇到的问题
1.多个数取最大
max(a,max(b,c))
96.不同的二叉搜索树
一、做题感受&第一想法
- 动规五要素分析
- dp和i的定义:dp[i]指 i 个节点的二叉搜索树共有多少种树型
- 递归公式:
dp[i] += dp[j] * dp[i-j-1], 0 <= j <= i - 1
(左子树 j 个节点,右子树 i - j - 1个节点。总树型为 左子树的树型数 乘以 右子树的树型数) - 初始化:dp[0] = 1,dp[1] = 1
- 遍历顺序:从前往后
- 手算序列(略)
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n+1,0);
dp[0] = 1;
dp[1] = 1;
for(int i = 2;i <= n;i++){ //dp[i]
for(int j = 0;j <= i - 1;j++){ //左子树:j,右子树:i-j-1
dp[i] += dp[j] * dp[i-j-1]; //递推公式
}
}
return dp[n];
}
};