数学-剪绳子-JZ67

描述
给你一根长度为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

思路:
本题采用 记忆递归法

  1. 递归函数的设计和功能:track(n); 含义是:求长度为n的数,最后分段后的最大乘积,这里我们不需要关心分成多少段
  2. 递归函数的终止条件: 如果n <= 4, 显然track(n) = n
  3. 下一步递归:对于长度n,我们需要减少递归参数n,
    如果第一段为1, 显然下一步递归为track(n-1)
    如果第一段为2,则下一步递归为 track(n-2)…
    因为要至少分2段,所以,最后一次可能的情况为最后一段为n-1,因此,每一步可能的结果为 1 * track(n-1), 2 * track(n-2), …, (n-1) * track(1),在n-1种情况中取一个最大值即可。
    这里我们不用关心track(n-1)等的值为多少,减少一次计算

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

代码

public class Solution {
    public int cutRope(int target) {
        if (target == 2) {
            return 1;
        }
        if (target == 3) {
            return 2;
        }
        int [] arr = new int[target+1];
        return track(target, arr);
    }
    
    private int track(int target, int [] arr) {
        if (target <= 4) {
            return target;
        }
        if (arr[target] != 0) {
            return arr[target];
        }
        int res = 0;
        for (int i = 1; i < target; i++) {
            res = max(res, i * track(target-i, arr));
        }
        arr[target] = res;
        return arr[target];
    }
    private int max(int x, int y) {
        return x > y ? x : y;
    }
}
上一篇:sgd Momentum Vanilla SGD RMSprop adam等优化算法在寻找函数最值的应用


下一篇:cf730 B Customising the Track