题目描述
给你一根长度为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。
问题的分析
4 : 2x2
5 : 2x3
6 : 3x3
7 : 2x2x3 或者4x3
8 : 2x3x3
9 : 3x3x3
10:2x2x3x3 或者4x3x3
下面是分析: 首先判断k[0]到k[m]可能有哪些数字,实际上只可能是2或者3。 当然也可能有4,但是4=2x2,我们就简单些不考虑了。 5<2*3,6<3*3,比6更大的数字我们就更不用考虑了,肯定要继续分。其次看2和3的数量,本着3越多乘积越大的本质,只存在3种情况,情况一目标数除以三余1,则将1与一个3相加合成为4=2*2的形式然后将所有的乘数求积就可以了。情况二目标数除以三余2,将所有的乘数求积就可以了。情况三目标数能被三整除,将所有的乘数求积就可以了。
我的代码
public class Solution {
public int cutRope(int target) {
int result=0;
if(target==2){return 1;}
if(target==3)return 2;
if(target==4)return 4;
if(target>3&&target<=60){
result=1;
int x=target%3;
int n=target/3;//是3的n倍
int flag=1;//标志位,是否仅余2
if(x==1){
n=n-1;
}else if(x==2){
flag=2;//如果仅余2则最后乘2
}else{
}
for(int i=0;i<n;i++){
result*=3;
}
return result*flag;
}
return result;
}
}
别人的代码
链接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?f=discussion
来源:牛客网
public int cutRope(int target) {
int max=1;
if(target<=3 && target>0){
return target-1;
}
while(target>4){
target-=3;
max*=3;
}
return max*target;
}
这位大神写的代买就比我简洁优雅许多。核心的想法基本一致。
利用动态规划的求解
我在做玩题目之后在题解区看到的另一个解法,我们可以吧问题分成更小的问题,解决小问题再将小问题的解组合为大问题的解。(动态规划的思想)本题中,我们将大的问题细分,例如对于4来说,max[0-3]中存储了4的因子,max[0]=0只是用来占位。4可以分为1,3或2,2,分别计算max[1]*max[4-1]和max[2]*max[4-2],比较二者并取最大值存放在max[4]中,以此类推大于4的值,最后返回目标值max[target]就可以了。
public class Solution {
public int cutRope(int target) {
if (target<2)return 0;
if (target==2)return 1;
if (target==3)return 2;
int[] max=new int[target+1];
max[0]=0;
max[1]=1;
max[2]=2;
max[3]=3;
for (int i=4;i<target+1;i++){
int temp=0;
for (int j=1;j<=i/2;j++){
int num=max[j]*max[i-j];
if (temp<num){
temp=num;
}
}
max[i]=temp;
}
return max[target];
}
}