剑指Offer-14-剪绳子/力扣-343-整数拆分
动态规划
动态规划的思路是什么?
对于一段绳子,第一刀下去可以将绳子分成i和n-i两段,其中i的取值范围为[1,n-1]
dp[n]表示n可分成的最大乘积和,dp[n] = max(dp[n],max(i*n-i,i*f(n-i)))
初始化:全部初始化为1
为什么有两层max()
要与一个额外的i-j
作比较?因为dp[i-j]
代表的是将绳子 break 之后的最大值,缺少一个不 break 的情况
int cuttingRope(int n) {
vector<int> dp(n, 1);
for (int i = 2; i <= n; i++) {
for (int j = 1; j < (i + 1) / 2; j++) {
dp[i - 1] = max(max(j * dp[i - j - 1], j + i - j), dp[i - 1]);
}
}
return dp[n - 1];
}
这里的 dp 数组不能被优化成常数个变量
Ⅱ
和 Ⅰ 有什么区别?多了一步取模运算,Ⅱ 的数据范围更大了,从 58 变成了 1000,不在过程中取模是不可能的了,因为 INT 范围肯定会超,那么就不能用动态规划了,也就是说题目是要求换一种方法求解
贪心
我觉得想出来贪心策略…怎么证明是个数学问题,怎么想出来则是一个玄学问题
力扣的编译器 res 用 int 怎么都会中间计算溢出,所以定义为 long
int MOD = 1e9 + 7;
int cuttingRope(int n) {
// 当 n >= 5 时,尽可能多地去剪长度为 3 的绳段
// 2->1,3->2,4->4,5->6
if (n < 4)return n - 1;
long res = 1;
while (n >= 5) {
res = (res * 3) % MOD;
n -= 3;
}
return (res * n) % MOD;
}