《劍指offer》14.剪繩子

注:此博客不再更新,所有最新文章將發表在個人獨立博客limengting.site。分享技術,記錄生活,歡迎大家關注

題目描述:
給你一根長度爲n的繩子,請把繩子剪成m段(m和n都是整數,n > 1,m > 1),每段繩子的長度記爲k[0],k[1],k[2]…k[m]。請問k[0] * k[1] * … * k[m]可能的最大乘積是多少?例如,當繩子的長度爲8時,我們把它分別剪成2,3,3的三段,此時乘積最大是18。

思路一:利用動態規劃,自下而上的循環,原理同斐波那契數列,時間複雜度O(n²),空間複雜度O(n)

public class CutThread {
    public static int maxProductAfterCutting(int length) {
        if (length < 1) return -1;

        int[] res = new int[length + 1];
        res[0] = 0;
        res[1] = 1;
        res[2] = 2;
        res[3] = 3;
        for (int i = 4; i <= length; i ++) {
            int max = 0;
            for (int j = 1; j <= i / 2; j ++) {
                int tmp = res[j] * res[i - j];
                if (tmp > max) max = tmp;
            }
            res[i] = max;
        }
        return res[length];
    }
    public static void main(String[] args) {
        System.out.println(maxProductAfterCutting(15));
    }
}

思路二,貪婪算法,儘可能剪長度爲3的繩子,如果最後的餘數是1,則將最後一個3和剩下的1拼成4不剪斷,時間複雜度O(1),空間複雜度O(1)

證明:當n >=5 時,有剪成2,3,4,5四個選擇,剪成2和4是等價的,因爲2 × 2 = 4,剪成5不如把5分成2 × 3 = 6,在2和3中易證3(n - 3) >= 2(n - 2) > n,故應該儘可能多地將繩子剪成長度爲3的段,但是如果n = 4,4 > 3 * 1,故保持4不剪。

import static java.lang.Math.pow;

public class CutThread {
    public static int maxProductAfterCutting(int length) {
        if (length < 1) return -1;

        int timesOf3 = length / 3;
        if (length % 3 == 2) return 2 * (int)pow(3, timesOf3);
        if (length % 3 == 1) return 4 * (int)pow(3, timesOf3 - 1);
        else return (int)pow(3,timesOf3);
    }
    public static void main(String[] args) {
        System.out.println(maxProductAfterCutting(15));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章