题目描述:
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),
每段绳子的长度记为 k[0],k[1]...k[m-1] 。
请问k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?
例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
题解:
class Solution {
int[] res = null;
public int cuttingRope(int n) {
res = new int[n+1];
res[2] = 1;
for(int k=2;k<=n;k++){
run(k);
}
return res[n];
}
public void run(int i){
int cmp = 1;
for(int j=2;j<=i;j++){
int med = Math.max(j,res[j]);
cmp = Math.max(cmp, med*(i-j));
}
res[i] = cmp;
}
}
思路详解
假设输入值为n,输出值为S(n),则
S(8) = (8-7) * S(7)
S(8) = (8-6) * S(6)
S(8) = (8-5) * S(5)
......
S(8) = (8-2) * S(2)
即n=8时,可能的情况有以上几种。
但是,在S(8) = (8-7) * S(7)中,S(7)意味着长度为7的那段绳子至少被剪断一次,这与题意不符因为显然存在S(8) = 1 * 7的情况。所以对之前的分析还有缺陷。
因为要求最大乘积,所以需要在S(7)和7之间取较大值,则将上述表达式进行修改
S(8) = (8-7) * max[S(7), 7]
S(8) = (8-6) * max[S(6), 6]
S(8) = (8-5) * max[S(5), 5]
......
S(8) = (8-2) * max[S(2), 2]
即S(8)=上述6种情况的最大值。
每计算出一个S(n),将这个值保存到数组中,方便在求后面值的时候调用。
空间复杂度:O(n)
求长度为n的绳子,需要空间为n+1(空间也可以为n,但是为了使数组序号与绳子长度对应起来,使用n+1的空间)的数组。
时间复杂度:O(n²)
计算S(n)需要先计算S(2),S(3),S(4),......S(n-1)