剑指Offer(Java实现):剪绳子

题目
给你一根长度为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。

思路
1.动态规划方法
四个特点:
①求一个问题的最优解;
②整体的问题的最优解是依赖于各个子问题的最优解;
③小问题之间还有相互重叠的更小的子问题;
④从上往下分析问题,从下往上求解问题;

这其实有点像斐波那契数列的思路,就是把绳子分成若干段,再把若干段分成小段,一直分到最长度为2即f(2)的时候,因为很容易知道f(1),f(2),f(3),我们就能得到f(4),f(5)这样从下向上再计算问题,最终求得解。

2.贪婪算法
当n>=5时,尽可能多地剪长度为3的绳子;当剩下绳子长度为4时,把绳子剪成两段。
ps:为什么尽可能剪成长度为3呢,因为当n>=5时,3(n-3)>=2(n-2)==> n>=5,
为什么不是4或者5或者更多呢,是因为可以把5又分成2和3,4又分成了2和2,所以是3。

复杂度分析
动态规划时间复杂度是O(n^2),空间复杂度O(n);
贪婪算法时间空间复杂度都是O(1).
在这里插入图片描述
代码

package Offer;

public class T14 {
    //剪绳子问题-动态规划
    public static int solution(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 = 0;
        for(int i = 4; i <=length; i++){
            for(int j = 1; j <= i/2; j++){
                int product = products[j] * products[i - j];
                if(max < product)
                    max = product;

                products[i] = max;
            }
        }

        max = products[length];

        return max;
    }

    //剪绳子-贪婪算法
    public static int solution2(int length){
        if(length < 2)
            return 0;
        if(length == 2)
            return 1;
        if(length == 3)
            return 2;

        //剪长度为3的绳子段
        int size = length/3;
        //当剩下的长度为4时,应该剪长度为2的两段
        if(length - size*3 == 1)
            size -= 1;

        int size0f2 = (length - size*3)/2;

        return (int)(Math.pow(3,size))*(int)(Math.pow(2,size0f2));
    }

    public static void main(String[] args) {

        long startTime1 = System.nanoTime();
        int b = solution(6);
        long endTime1 = System.nanoTime();
        System.out.println("结果"+b+" 动态规划时间"+(endTime1-startTime1)+"ms");


        long startTime=System.nanoTime();   //获取开始时间
        int c = solution2(7);
        long endTime=System.nanoTime(); //获取结束时间
        System.out.println("结果:"+c+" 贪婪时间: "+(endTime-startTime)+"ms");
    }

}

发布了49 篇原创文章 · 获赞 4 · 访问量 2500

猜你喜欢

转载自blog.csdn.net/weixin_42040292/article/details/104187420