剪繩子問題and leetcode343

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章