剑指Offer-题14(Java版):剪绳子

参考自:《剑指Offer——名企面试官精讲典型编程题》

题目:剪绳子
给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]k[1]…k[m]可能的最大乘积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。

主要思路
思路一:动态规划:f(n) = max(f(i)*f(n-i)), 其中 0<i<n,从1到n/2遍历i,求出最大的f(n) 。为了避免重复计算,选择从下到上的顺序计算。

思路二:贪婪算法:当n大于等于5时,尽可能剪长度为3的绳子,当剩下长度为4时,把绳子剪成2段长度为2的绳子。
证明:n≥5时,2(n-2)>n, 3(n-3)>n, 并且3(n-3)≥2(n-2)
n=4时, 2×2>3×1

关键点:动态规划,贪婪算法

时间复杂度:动态规划:O(n^2);贪婪算法:O(1)

public class CutRope
{
    public static void main(String[] args)
    {
        int length = 8;
        int expected = 18;
        int result = maxProductAfterCutting1(length);
        System.out.println(result);
        System.out.println(maxProductAfterCutting2(length));
    }

    /**
     * 动态规划
     *
     * @param length
     * @return
     */
    private static int maxProductAfterCutting1(int length)
    {
        if (length < 2)
            return 0;
        if (length == 2)
            return 1;
        if (length == 3)
            return 2;

        int[] products = new int[length + 1];
        products[0] = 0;
        products[1] = 1;
        products[2] = 2;
        products[3] = 3;

        int max;
        for (int i = 4; i <= length; ++i)
        {
            max = 0;
            //f(n) = max(f(i)*f(n-i))   0<i<n
            for (int j = 1; j <= i / 2; ++j)
            {
                int currentProduct = products[j] * products[i - j];
                if (max < currentProduct)
                    max = currentProduct;
            }
            products[i] = max;
        }
        max = products[length];
        return max;
    }

    /**
     * 贪婪算法
     * @param length
     * @return
     */
    private static int maxProductAfterCutting2(int length)
    {
        if(length < 2)
            return 0;
        if(length == 2)
            return 1;
        if(length == 3)
            return 2;

        // 尽可能多地减去长度为3的绳子段
        int timesOf3 = length / 3;

        // 当绳子最后剩下的长度为4的时候,不能再剪去长度为3的绳子段。
        // 此时更好的方法是把绳子剪成长度为2的两段,因为2*2 > 3*1。
        if(length - timesOf3 * 3 == 1)
            timesOf3 -= 1;

        int timesOf2 = (length - timesOf3 * 3) / 2;

        return (int) (Math.pow(3, timesOf3)) * (int) (Math.pow(2, timesOf2));
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37862405/article/details/80152564