题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
思路
-
动态规划
-
递推公式
f(n) = 0 n = 1 f(n) = 1 n = 2 f(n) = 2 n = 3 f(n) = max{dp(i) * dp(n-i)} n > 3, 1<=i<=n-1
-
注意:当
n <= 3
时因为必须剪至少一次的缘故,导致f(1)=0, f(2)=1*1=1, f(3)=1*2=2
;但是当n>=4
时,将n<=3
的部分单独作为一段能提供更大的乘积因此,初始化时应该
dp[1]=1≠f(1), dp[2]=2≠f(2), dp[3]=3≠f(3)
,同时将f(1), f(2), f(3)
单独返回 -
时间复杂度:
O(N^2)
,空间复杂度:O(N)
-
-
贪心
-
当
n>=5
时,尽可能多剪长度为 3 的绳子;当n=4
时,剪成两段长度为 2 的绳子 -
证明
当 n >= 5 时,可以证明: 3(n-3) > 2(n-2) > n 当 n == 4 时,2*2 > 3*1
-
时间复杂度:
O(1)
,空间复杂度:O(1)
-
**Code **
class Solution {
public:
int cutRope(int number) {
if (number <= 1)
return 0;
if (number == 2)
return 1;
if (number == 3)
return 2;
vector<int> backup = { 0,1,2,3 }; //这里被减去的绳子段与前面返回结果的值有所不同
for (int i = 4; i != number + 1; i++) {
int j = i / 2; //一般趋于最中间的两个数乘积是最大的,因为正方形面积最大。
backup.push_back(backup[j] * backup[i - j]);
}
return backup[number];
}
};