描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
返回值描述:
输出答案。
示例1
输入: 8
返回值: 18
思路:
本题采用 记忆递归法
- 递归函数的设计和功能:track(n); 含义是:求长度为n的数,最后分段后的最大乘积,这里我们不需要关心分成多少段
- 递归函数的终止条件: 如果n <= 4, 显然track(n) = n
- 下一步递归:对于长度n,我们需要减少递归参数n,
如果第一段为1, 显然下一步递归为track(n-1)
如果第一段为2,则下一步递归为 track(n-2)…
因为要至少分2段,所以,最后一次可能的情况为最后一段为n-1,因此,每一步可能的结果为 1 * track(n-1), 2 * track(n-2), …, (n-1) * track(1),在n-1种情况中取一个最大值即可。
这里我们不用关心track(n-1)等的值为多少,减少一次计算
时间复杂度:O(n^2)
空间复杂度:O(n)
代码
public class Solution {
public int cutRope(int target) {
if (target == 2) {
return 1;
}
if (target == 3) {
return 2;
}
int [] arr = new int[target+1];
return track(target, arr);
}
private int track(int target, int [] arr) {
if (target <= 4) {
return target;
}
if (arr[target] != 0) {
return arr[target];
}
int res = 0;
for (int i = 1; i < target; i++) {
res = max(res, i * track(target-i, arr));
}
arr[target] = res;
return arr[target];
}
private int max(int x, int y) {
return x > y ? x : y;
}
}