动态规划:整数拆分
343. 整数拆分
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
思路
动规五部曲
-
确定dp数组(dp table)以及下标的含义
dp[i]:分拆数字i,可以得到的最大乘积为dp[i]。 -
确定递推公式
dp[i]最大乘积:可以从1遍历j,然后有两种渠道得到dp[i]。- 一个是j * (i - j) 直接相乘。
- 一个是j * dp[i - j],相当于是拆分(i - j)。
j是从1开始遍历,在遍历j的过程中其拆分的情况都计算过了。
递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
-
dp的初始化
严格从dp[i]的定义来说,dp[0] dp[1] 就不应该初始化,也就是没有意义的数值。
所以只初始化dp[2] = 1(拆分数字2,得到的最大乘积是1)。 -
确定遍历顺序
dp[i] 是依靠 dp[i - j]的状态,所以遍历i一定是从前向后遍历,先有dp[i - j]再有dp[i]。
枚举j的时候,是从1开始的。i是从3开始,这样dp[i - j]就是dp[2],正好可以通过初始化的数值求出来。 -
举例推导dp数组
举例当n为10 的时候,dp数组里的数值,如下:
代码
class Solution {
public int integerBreak(int n) {
int[] dp = new int[n+1];
dp[2] = 1;
for(int i=3;i<=n;i++){
for(int j=1;j<i-1;j++){
dp[i] = Math.max(dp[i],Math.max((i-j)*j,dp[i-j]*j));
}
}
return dp[n];
}
}