题目描述
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
注:2 <= n <= 58
示例1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
来源:力扣Leetcode
解题方法
/**
* @author IT00ZYQ
* @date 2021/6/6 22:54
**/
public class 剪绳子 {
/**
* 暴力递归 + 缓存 =》 简单的动态规划
* @param n 绳子原始长度
* @return 最大乘积
*/
public static int cuttingRope(int n) {
// 缓存表
int[] dp = new int[n+1];
return cutting(n, n, dp);
}
/**
* 求绳子长度为n的最大乘积
* @param n 绳子长度
* @param maxN 绳子原始长度
* @param dp 缓存
* @return 最大乘积
*/
public static int cutting(int n, int maxN, int[] dp) {
// dp[n] != 0 代表该过程已经算过,直接返回
if (dp[n] != 0) {
return dp[n];
}
// base case 递归出口 绳子长度为0或为1时,只剩一种情况,返回1
if (n == 0 || n == 1) {
return 1;
}
// 循环尝试各个长度
// 由于至少需要分成两段,所以每一段绳子长度都必须小于绳子的原始长度)i < maxN)
int max = cutting(n - 1, maxN, dp);
for (int i = 2; i <= n && i < maxN; i++) {
max = Math.max(i * cutting(n - i, maxN, dp), max);
}
// 添加缓存
dp[n] = max;
return max;
}
public static void main(String[] args) {
System.out.println(cuttingRope(8));
}
}