代码随想录链接:代码随想录
思路:
(1).确定dp数组的含义:
dp[i]:分拆数字i,可以得到的最大乘积为dp[i]
(2).确定递推公式:
dp[i]最大乘积是怎么得到:
其实可以从1遍历j,然后有两种渠道得到dp[i].
一个是j * (i - j)直接相乘。
一个是j * dp[i - j],相当于是拆分(i - j)
因此递推公式为:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j))
注意这里在确定dp[i]时从1到i遍历j时更新dp[i]需要比较三个内容,分别是原始的dp[i],j*(i-j)以及j*dp[i-j],取这三个数的最大值更新dp[i]
(3).初始化dp数组:
严格从dp[i]的定义来说,dp[0] dp[1] 就不应该初始化,也就是没有意义的数值
只初始化dp[2] = 1,从dp[i]的定义来说,拆分数字2,得到的最大乘积是1,这个没有任何异议
(4).确定遍历顺序:
遍历i一定是从前向后遍历,先有dp[i - j]再有dp[i]
枚举j的时候,是从1开始的,从0开始的话,那么让拆分一个数拆个0,求最大乘积就没有意义
j的结束条件是 j < i - 1 ,其实 j < i 也是可以的
但是j的遍历只需要遍历到i/2(包含)就可以,后面就没有必要遍历
Java代码:
class Solution {public int integerBreak(int n) {//dp[i] 为正整数 i 拆分后的结果的最大乘积int[] dp = new int[n+1];dp[2] = 1;for(int i = 3; i <= n; i++) {for(int j = 1; j <= i/2; j++) {// 这里的 j 其实最大值为 i-j,再大只不过是重复而已,//并且,在本题中,我们分析 dp[0], dp[1]都是无意义的,//j 最大到 i-j,就不会用到 dp[0]与dp[1]dp[i] = Math.max(dp[i], Math.max(j*(i-j), j*dp[i-j]));// j * (i - j) 是单纯的把整数 i 拆分为两个数 也就是 i,i-j ,再相乘//而j * dp[i - j]是将 i 拆分成两个以及两个以上的个数,再相乘。}}return dp[n];}
}