1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//leetcode submit region begin(Prohibit modification and deletion)
class Solution1 {
//dp : 时间复杂度 0(n2) , 空间复杂度o(n)
// 数学结论是:一个数n,拆成m个接近相同的数,可以得到最大乘积值
// 定义dp[i]数组为 整数i可拆为的最大的乘积
//用最小数j去试着遍历i, 那么i拆成 j * (i-j),即可以理解为拆成2个数j 和 i-j,
// 同时也可以用dp数组表示为 j*dp[i-j], 即最小尝试单元数j(无需再拆分) 和对 i-j的拆分 dp[i-j]
// 那么可得到dp数组的的递推公式 dp[i] = max(dp[i], max(j * (i-j), j*dp[i-j]));
// 注意:需对 用j遍历i的内层for循环得到的多个dp[i] 也进行max比较,从而求最大值
public int integerBreak(int n) {
int[] dp = new int[n + 1];
dp[2] = 1;
for (int i = 3; i <= n; i++) {
//由题目条件可推出,dp[0],dp[1]无法拆分,没有实际意义
//dp[2] =1, 那么j = 3 - 2,所以j从1开始,由前面拆分最大乘积的数学结论,那么j的边界条件可以优化为j < i/2
// for (int j = 1; j < i; j++) {}
//对于i的最大值,内层for循环会得出多个dp[i],所以dp[i]也需要参与和Math.max(j, dp[i - j])比较来求最值
for (int j = 1; j <= i / 2; j++) {
dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
}
}
return dp[n];
}
}
|