题目:给你一根长度为n的绳子,把绳子剪成m段(m、n都为整数,n>1,m>1)每段绳子长度为m1,m2,m3,...,mn,求m1*m2*m3*...*mn的最大乘积是多少?例如,绳子长度8,把绳子剪成2,3,3,此时乘积最大为18.
思路一:动态规划,从小往大,从长度为1的绳子开始算最大乘积是多少,假如绳子为1时为f(1)=1,绳子为2时为f(2)=1,绳子为3时为f(3)=2,那么当绳子为4就是max(f(1)*f(3),f(2)*f(2)),以此类推,直到f(n)。
解法一:时间复杂度为O(n^2),空间复杂度为O(n)
package question14;
public class Test1 {
public static void main(String[] args) {
System.out.println(maxProductAfterCutting(10));
}
private static int maxProductAfterCutting(int length) {
if(length<2)
return 0;
if(length==2)
return 1;
if(length==3)
return 2;
int[] product=new int[length+1];
//绳长为1,2,3
product[1]=1;
product[2]=2;
product[3]=3;
int max=0;
//绳长大于4后开始计算
for(int i=4;i<=length;i++){
max=0;
for(int j=1;j<=i/2;j++){
int temp=product[j]*product[i-j];
if(max<temp)
max=temp;
}
product[i]=max;
}
return product[length];
}
}
思路二:贪婪算法,通过举例分析可以发现,4分为2 2,5分为2 3,6分为3 3,7分为2 2 3,8分为2 3 3,9分为3 3 3,10分为2 2 3 3,当n>=5时,绳子应该尽量分成长度为3的,但到最后不能剩下长度为1,比如10分成2 2 3 3,乘积为36,分成1 3 3 3,乘积为27,所以一开始分绳子就直接拼长度为3的,不够就拼长度为2.
解法二:时间复杂度为O(1),空间复杂度为O(1)
public class Test2 {
public static void main(String[] args) {
System.out.println(maxProductAfterCutting(10));
}
private static int maxProductAfterCutting(int length) {
if(length<2)
return 0;
if(length==2)
return 1;
if(length==3)
return 2;
int num3Count=length/3;
if(length-3*num3Count==1){
num3Count-=1;
}
int num2Count=(length-3*num3Count)/2;
int max=3*num3Count+2*num2Count;
return max;
}
}