剪繩子 整數劃分 動態規劃與貪婪 劍指offer編程題整理 leetcode每日算法題

動態規劃

獨立子問題?最優解?貪心?

1大問題可以分解成小問題,大問題的最優解包括小問題的最優解,那麼可以求出小問題的最優解,存到數組中,在求大問題最優解時就可以直接從數組中獲取,最終獲得最優解。

2動態規劃:如果要求一個問題的最優解,而且該問題能分成若干個子問題,整體問題的最優解依賴於子問題的最優解,可以考慮用動態規劃解決。動態規劃一般是自頂向下思考,自底向上實現的,爲了避免計算子問題時重複,可以將子問題的結果打表記錄下來。

3貪心法:使用貪心法解決問題,要從數學上證明這個貪心策略一定能取到最優解,這樣每一步都做貪心選擇,實現起來要容易很多。

整數劃分問題

動態規劃與貪婪 剪繩子 12477 32.27%

給你一根長度爲n的繩子,請把繩子剪成整數長的m段(m、n都是整數,n>1並且m>1),每段繩子的長度記爲k[0],k[1],...,k[m]。請問k[0]xk[1]x...xk[m]可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別爲2、3、3的三段,此時得到的最大乘積是18。輸入一個數n,意義見題面。(2 <= n <= 60)

變式:切割杆,現有長度爲n的杆,價值數組是prices[],數組長度是n,已知長度i對應的價值是prices[i-1],比如長度1對應的價值數是prices[0]。將其切割,求碎片的最大價值。

1) 將n劃分成若干正整數之和的劃分數。
2) 將n劃分成k個正整數之和的劃分數。
3) 將n劃分成最大數不超過k的劃分數。
4) 將n劃分成若干奇正整數之和的劃分數。
5) 將n劃分成若干不同整數之和的劃分數。

 

鏈接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?orderByHotValue=1&questionTypes=000100&mutiTagIds=592&page=1&onlyReference=false
來源:牛客網

 /**
     * @param target
     * @return
     *
     * 分類:最值型、劃分型
     *
     * 考慮最後一步:
     * 必然有一個點,把target分成兩段,兩段分別構成最小子問題。
     * 兩段的最大值的乘積,也是target所求的最大值。
     * 設劃分點爲i,f[i]表示長度爲i的繩子的乘積最大值。
     *
     * 轉移方程:
     * f[i] = MAX{f[j]*f[i-j]}|0<j<i
     *
     * 那麼我們求的就是f[target]
     *
     * 初始值:
     * f[0]=1
     * f[1]=1
     *
     * 邊界情況:
     * 無
     *
     * 計算順序:
     * i從1到target
     * j從1到i
     */
    public int cutRope(int target) {
        int[] f = new int[target+1];
        //初始化
        f[0] = 0;
        f[1] = 1;
        for (int i = 1; i <= target; i++) {
            /**
             * 處理不分割的情況,因爲繩子不能不被分割
             */
            if(i==target) {
                f[i] = 1;
            }
            else {
                f[i] = i;
            }
            for (int j = 1; j < i; j++) {
                f[i] = Math.max(f[i],f[j]*f[i-j]);
            }
        }
        return f[target];
    }

上面解法有暴力窮舉的思想,遞推問題都可以這麼做

從i=1開始記錄出每個長度i的繩子,最大乘積fi記錄在數組f

對於每個fi需要轉換爲前幾個狀態的表達,即狀態方程,才能求解

劃分問題,引入一個變量j,代表從0~i的一種劃分

至於本題,是取乘積最大對劃分。

至於切割杆,是取劃分後兩部分價值最大。

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