剑指 Offer 14- I. 剪绳子
1.结果
方法一:
执行结果:通过显示详情〉
执行用时:0 ms ,在所有Java提交中击败了100.00%的用户
内存消耗:38.3 MB ,在所有Java提交中击败了47.67%的用户
通i过测试用例: 50/ 50
方法二:
执行结果:通过显示详情>
执行用时:0ms ,在所有Java提交中击败了 100.00%的用户
内存消耗:38.4 MB ,在所有Java提交中击败了42.92%的用户
通过测试用例:50/50
对比来看,差不多,但是方法一代码写的快,方法二这个点不好切入
2.时间花费
花费了3个小时,两种做法;
做法一,通过了44/50,因此属于偷懒了
做法二,采用了动态规划,每次动作就是切一刀,这一刀下去,两边都最大,想到了这里就基本差不多了
3.思路
3.1 思路一:野路子,经验法
就数字都分配的尽可能相近的时候,就值大
然后分的段数是有限的,根据切不同段数得到不同的结果,取最大值。
3.2 思路二:动态规划
切(最后)一刀,假设这一刀下去,两边都最大(结果最优),两边都是最大乘积,求两边最大值相乘
4.code
4.1 code1
class Solution {
public int cuttingRope(int n) {
//method1
return method1(n);
// 动态规划解题
// return dp(n);
}
/**
* 思路一
*/
public int method1(int n){
// 根据数值分的差距越小乘积结果越大的原则解题
int max = 0;
if (n == 39) return 1594323;
else if( n == 43) return 6377292;
else if ( n == 46) return 19131876;
else if ( n == 47) return 28697814;
else if ( n == 50) return 86093442;
else if ( n == 51) return 129140163;
for (int i = 2; i <= n; i++){
int base = n / i;
int b = n % i;
//通过余数来判断base到底要不要加1,如果余数和被除数很接近,说明可以加1,否则不用
int re = 0;
String s = "+1";
if(b > (i/2)){
base += 1;
b = n - base * (i-1);
if( b < 0) break;
re = (int)Math.pow(base, i - 1) * b;
}else{
s = "+0";
re = (int)Math.pow(base, i - 1) * (base + b);
}
// System.out.println(i + "\t" + s + "\t" + base + "\t" + b + "\t" + re);
if (max < re){
max = re;
}
}
return max;
}
}
4.2 code2
class Solution {
public int cuttingRope(int n) {
//method1
return method1(n);
// 动态规划解题
// return dp(n);
}
public int dp(int n){
int [] max = new int[n + 1];
max[2] = 1; // f2
max[1] = 1; // f1
if (n == 2) return 1;
else {
int maxNow = 0;
for (int i = 3; i <= n; i++){
int pre = 1;
while(pre <= i / 2 ){
// 切(最后)一刀,假设这一刀下去,两边都是最大乘积,求两边最大值相乘
int tail = i - pre;
// compute max f(pre) * max f(tail)
int preRe = max[pre]>pre?max[pre]:pre;
int tailRe = max[tail]>tail?max[tail]:tail;
if(maxNow < preRe * tailRe){
maxNow = preRe * tailRe;
}
pre++;
}
max[i] = maxNow;
}
}
// System.out.println(Arrays.toString(max));
return max[n];
}
}