《剑指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));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章