剑指offer面试题14(java版):剪绳子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/littlehaes/article/details/91411165

welcome to my blog

剑指offer面试题14(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

思路

  • 动态规划: 注意子问题和子子问题的关系, 比如:我们把长为3的绳子剪成1,2或者2,1两种, 而不考虑1,1,1这种情况, 也就是只剪一次

动态规划求解的问题的特点

  • 求一个问题的最优解
  • 整体问题的最优解依赖各个子问题的最优解
  • 把大问题分解成若干个小问题, 这些小问题之间还有相互重叠的更小的子问题
  • 从上往下分析问题,从下往上求解问题

复杂度

时间复杂度: O(n^2)
空间复杂度: O(n)

    public static int maxProductAfterCutting_solution(int length){
        if(length < 2) // 长度小于2没法切. 长度为1的绳子没法切;但是某个绳子切完后可以包含长为1的绳子,注意这二者的区分
            return 0;
        if(length==2)
            return 1;
        if(length==3)
            return 2;
        // products的索引为1,2,3时只是表示绳子长度为1,2,3
        // products的索引i大于3时,表示长为i的绳子剪切后各段乘积能得到的最大值
        int[] products = new int[length+1]; // 长度加一后,最后一个索引是length, 方便表示
        products[1] = 1;
        products[2] = 2;
        products[3] = 3;
        for(int i=4; i<=length; i++){
            // for(int j=1; j<=i-1; j++){ //长为i的绳子,切割位置可以是{1,2,3,...i-1}
            for(int j=1; j<=i/2; j++){ // 长为3的绳子,可以切成1,2; 2,1; 效果是一样的,所以只用切i/2次就行    // 可能要问不是还能切成1,1,1这种吗? 为什么只切1次? 1,1,1这种情况在1,2中已经考虑过了,1,1是2的两个子问题. 这里要明确子问题与更小的子问题的关系
                if(products[i] < products[j]*products[i-j])
                    products[i] = products[j]*products[i-j];
            }
        }
        return products[length];
    }

猜你喜欢

转载自blog.csdn.net/littlehaes/article/details/91411165