參考劍指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了吧。一家之言。望大佬們指正。