题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],...,k[m]。请问k[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
思考
在潜意识中,有这么一个小学或者初中数学题,给你一根长度一定的绳子,如果围成一个正方形,那么他的面积一定比围成长方形要大,最大的面积是围成圆形。
不知道为什么,看到这个题目想到了这个。
绳子分成的段数确定的时候,是不是要把各个段让他尽量平均呢,我们通过验证,发现确实是这样的,比如8分成2段,4*4比3*5是要大的,所以这个结论有了。
那么绳子到底分成几段合适呢? 我没有仔细考虑,直接枚举了分成的段数,从2、3、4、5....都分了试试,取最大值。
这样题目就通过了。
class Solution {
public:
int cutRope(int number) {
int ans=0;
for (int i=2; i<=number/2; i++) {
int p=number/i;
int o=number%i;
int s=1;
for (int j=1; j<=o; j++){
s=s*(p+1);
}
for (int j=1; j<=(i-o);j++){
s=s*p;
}
ans=max(ans,s);
}
return ans;
}
};
代码中: i枚举分成的段数,p代表每段的基本长度,o是余数,余数再直接加到每段上,有多少算多少,最后统计答案。
进一步思考
没想到那样就过了,但是我隐隐感觉到,分成的段数应该不用枚举也可以直接得出来,有一个规律或者结论在等着我发现,于是我机智的把通过了的代码在统计答案时同时把段数记录下来,发现确实分成的段数是极多的,什么叫极多,就是保证每一段的p都是2或者3.
再说仔细点儿,就是 这个题目的答案是尽可能多的3和不得已的2构成的。
18能被3整除,那么他最后的答案组成就是3 3 3 3 3 3
19不能被3整除,那么他最后的3有5个:3 3 3 3 3 剩下的4: 需要分成 2 2
因为4不能再拆成3和1了,显然3*1比2*2小。
所以得出结论
当这个数分到剩4的时候,直接2*2
剩3的时候,直接返回3
剩2的时候,直接返回2
所以说答案是把这个数n分成尽可能多的3,再凑最后的3种情况即可。
到这里,这个题目就可以随心所欲的写了,可以是递归,可以是循环结构。
递归版:
class Solution {
public:
int cutRope(int number) {
if (number==2) return 2;
if (number==3) return 3;
if (number==4) return 4;
return 3*cutRope(number-3);
}
};