参考剑指offer上的剪绳子问题,其中动态规划的方法有一部分我不是很理解,这里引用一下别人的部分代码。
public class Test {
public static void main(String[] args) {
int len = 10;
System.out.println(maxLen(len));
}
/**
* @param len绳子的长度
* @return
*/
private static double maxLen(int len) {
// lenCut[i]表示长度为i个的最优解 lenCut[3]比较特殊
double lenCut[] = new double[len + 1];
lenCut[0] = 0;
lenCut[1] = 1;
lenCut[2] = 2;
lenCut[3] = 3;
//初始化到3是因為3>1*2,其本身比分割的大,所以當分割比3大的數字時候,如5可以分成2,3,3就不繼續往下分割了
if (len < 2) {
return 0;
} else if (len == 2) {
return 1;
} else if (len == 3) {
return 2;
} else {
for (int i = 4; i <= len; i++) {
double max = 0;
for (int j = 1; j <= i / 2; j++) {
double temp = lenCut[j] * lenCut[i - j];
if (max < temp) {
max = temp;
}
}
lenCut[i] = max;
}
}
return lenCut[len];
}
}
其实我不是很理解这里的lenCut[3]=3.因为按照书上的思路对应的lenCut[3]对应的应该是长度为4时,可分割的最大长度,所以这里应该是4.
经过研究,我从另外一个角度来思考这个问题。将长度为n的绳子分为1与n-1是收益最低的,所以最短的且收益较大的需要从2开始考虑。同理3也是可以的,到4,可以分为2和2的情况,所以,在从上往下的递归思路中,收益最大的情况叶子节点是由2和3组成的,所以,在递归改为dp的时候,只需要存dp[2]和dp[3]即可。代表着长度为2和长度为3时不必继续分下去了。所以我的代码如下
class Solution {
public int integerBreak(int n) {
if(n<2){
return 0;
}
if(n==2) return 1;
if(n==3) return 2;
int []dp=new int[n+1];
dp[2]=2;
dp[3]=3;
int max=0;
for(int i=4;i<=n;i++){
dp[i]=Math.max(dp[i-2]*dp[2],dp[i-3]*dp[3]);
}
return dp[n];
}
}
我倒是觉得这个思路从一定程度上可以解释为什么最开始的代码里dp[3]=3了吧。一家之言。望大佬们指正。