题目描述

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],...,k[m]。请问k[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:输入一个数n,意义见题面。(2 <= n <= 60)
返回值描述:输出答案。
示例1
输入:8
返回值:18

题目分析

当绳子的长度长于2时,可以被剪成若干段,而这些段的长度可以是从1 ~ (绳子的长度-1),可以使用暴力法,遍历绳子的所有切割方法,求出里面最大的乘积。
图片说明

解题思路

方法1:暴力法,遍历可以分割的所有情况,取其中的最大值
在分析的思路里,对于子线段的长度范围是1 ~ (n-1),实际上,只需要1 ~ (n/2),因为大于n/2的情况,已经在前面出现过了,所以可以直接去掉。

图片说明

方法2:数学推导,可以知道如何乘积最大的切割方式
推导过程:
1、根据“算数几何均值不等式”可知:当 n1+n2+n3+..na= 绳子总长度不变时,有
图片说明
当且仅当n1=n2=n3..=na时,右边的值刚好能等于左边的值,不然都比左边值小;
则有推导结论1:当所有绳段长度相等时,乘积最大;

2、将绳子长度分为a段等长的x,满足 n = a*x,则绳子每段乘积为 x^a,因为 a= n/x,则有
x^a = x^(n/x) = (x^(1/x))^n,仅当(x^(1/x))取最大值时,乘积x^a为最大值。
对 y=x^(1/x) 求导,可知当且仅当 x = e时,导数y'=0(且x<e,y'>0递增;x>e,y'<0递减),则y在x=e处有极大值(呈峰状);
因为绳子只能剪成整数长度,而x=e(2.7),可已经选择的较大值为2和3,比较y(2)和y(3)可知
图片说明
取3的时候更大,其他的整数长度乘积都小于3;
则有推导结论2:最优的绳段长度为3;

实现过程:
1.当线段长度大于4时,优先分割长度为3的线段;
2.当长度小于等于4时,分割长度为2的线段。

代码实现

方法1:暴力遍历

public int cutRope(int target) {
    if(target<=1) return 1;
    if(target == 2) return 1;
    if(target == 3) return 2;
    int[] nums = new int[target+1];
    // 定义一些基本情况
    nums[0] = 1; nums[1] = 1; nums[2] = 2; nums[3] = 3;
    // 记录最大值
    int max = 0;
    for(int i=4;i<=target;i++){
        // 防止重复计算,只用计算到i/2
        for(int j=1;j<=i/2;j++){
            // 计算乘积
            int tmp = nums[j]*nums[i-j];
            if(tmp > max){
                max = tmp;
                nums[i] = max;
            }
        }
    }
    return max;
}

时间复杂度:O(n^2),需要两次循环,总循环次数为n*n/2,时间复杂度为O(n^2);
空间复杂度:O(n),需要空间大小为n+1的辅助数组nums;

方法2:数学推导法

public int cutRope(int target) {
        // 将一些基本情况直接返回
        if(target == 2){
            return 1;
        }else if(target == 3){
            return 2;
        }
        // 计算target中能分割出多少个长度为3的线段
        int a1 = target / 3;
        if((target-a1*3) == 1){
            a1--;
        }
        // 计算剩下的分割长度为2的线段
        int a2 = (target-a1*3)/2;
        // 求这些长度为3和2的线段乘积
        int max = (int)Math.pow(3,a1) * (int)Math.pow(2,a2);
        return max;
    }

时间复杂度:O(1),只需要计算即可,不用循环;
空间复杂度:O(1),只需要常量的变量数存储结果和一些值;