题目描述
给你一根长度为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。
输入描述
输入一个数n,意义见题面。(2 <= n <= 60)
输出描述
输出答案。
性能要求
时间限制:1秒 空间限制:65536K
题目分析
直接看题目是没有头绪,因而我们只有先一一列举几个,来查看是否有规律可循。
绳子长度n | 最大乘积 | 段数m | 公式 |
---|---|---|---|
2 | 1 | 2 | 1*1 |
3 | 2 | 2 | 2*1 |
4 | 4 | 2 | 2*2 |
5 | 6 | 2 | 3*2 |
6 | 9 | 2 | 3*3 |
7 | 12 | 3 | 3*4 |
8 | 18 | 3 | 3* 3*2 |
9 | 27 | 3 | 3* 3* 3 |
10 | 36 | 3 | 3* 3* 4 |
11 | 54 | 4 | 3* 3* 3* 2 |
12 | 81 | 4 | 3* 3* 3* 3 |
… | … | … | … |
由上表我们可以推断出,当绳子长度超过4后,要使得分段后每段长度乘积最大,需要满足公式为 3*m + x = n (m > 1 并且 m < n, x 属于 {2,3,4})。
因此根据该公式,我们在分段时,每次在总长度中减去3,直到剩下的那段长度x属于{2,3,4}。现在使用代码进行实现。
java实现
使用循环来得到结果
public class Solution {
public int cutRope(int target) {
if(target == 2){
return 1;
}else if(target == 3){
return 2;
}else if(target == 4){
return 4;
}
int result = 1;
while(target > 4 ){
result = result * 3;
target = target - 3;
}
return result * target;
}
}
使用递归实现
public class Solution {
public int cutRope(int target) {
if(target == 2){
return 1;
}else if(target == 3){
return 2;
}else if(target == 4){
return 4;
}
return process(target);
}
private int process(int target){
if(target <= 4){
return target;
}else {
return 3*process(target - 3);
}
}
}
使用上面两种方式,也是我能够想到的,它们都能达到性能要求,完成该题。但这不是最优算法。下面我贴出大佬们的解题思路。
优解
绳子长度n | 最大乘积 | 段数m | 公式 |
---|---|---|---|
2 | 1 | 2 | 1*1 |
3 | 2 | 2 | 2*1 |
4 | 4 | 2 | 2*2 |
5 | 6 | 2 | 3*2 |
6 | 9 | 2 | 3*3 |
7 | 12 | 3 | 3* 2*2 |
8 | 18 | 3 | 3* 3* 2 |
9 | 27 | 3 | 3* 3* 3 |
10 | 36 | 3 | 3* 3* 2*2 |
11 | 54 | 4 | 3* 3* 3* 2 |
12 | 81 | 4 | 3* 3* 3* 3 |
… | … | … | … |
由此推导出的公式为
当 n % 3 =1 时,最大乘积 = 3^k * 2 * 2,k = n / 3 -1;
当 n % 3 = 2时,最大乘积 = 3^k * 2, k = n / 3;
相应的java代码如下
public class Solution {
public int cutRope(int target) {
if (n == 2) return 1;
if (n == 3) return 2;
if (n % 3 == 1) {
int k = n / 3 - 1;
return (int)Math.pow(3, k) * 2 * 2;
}
if (n % 3 == 2) {
int k = n / 3;
return (int)Math.pow(3, k) * 2;
}
return (int)Math.pow(3, n / 3);
}
}
总结
方式一和方式二的差距是很大的。方式一仅仅是模拟出了规律,而方式二已经将这规律抽象为数学模型,思维的高度上了整整一个层次。我还需要多培养这方面的能力。