法1:动态规划
看了题解
想法:
- “给定一个正整数 n,将其拆分为至少两个正整数的和”。则 n >= 2
- 用数组dp保存整数 1 ~ n 经拆分后的最大乘积(后续需用到dp[1] = 1,比如 3 = 1 + 2)
- 拆分整数 i 时,先将其拆分为 i - j 和 j;最大值在下面几种情况中产生:
- (i - j) * j:即 i - j 和 j 均不再拆分
- dp[i - j] * dp[j]:即 i - j 和 j 均再拆分
- dp[i - j] * j:即只拆分 i - j
- (i - j) * dp[j] :即只拆分 j
- dp[i]:即之前 i 的拆分中的最大乘积
注:第3种情况与第4种情况本质上是一样的,因为j = 1 ~ i - 1,故只要考虑一个即可
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function(n) {
var dp = [];
var i = 0, j = 0;
for(i = 0; i <= n; i++) {
dp[i] = 0;
}
dp[1] = 1;
dp[2] = 1;
for(i = 3; i <= n; i++) { // 从3开始;先不给dp[2]赋值为1,从2开始也是可以的
for(j = 1; j < i; j++) { // 将i分为两部分:j 和 i - j
dp[i] = Math.max( // dp的最大值:
// 1. 分为两部分;
(i - j) * j,
// 2. 将两部分都再次拆分
// (各部分经过拆分得到的乘积最大值已经保留在dp中);
dp[i - j] * dp[j],
// 3. 只拆分一部分
dp[i - j] * j,
// 4. 只拆分另一部分
// (i - j) * dp[j],
// 因为j = 1 ~ i - 1,所以如果只拆分一部分,3和4其实效果相同
// 只要一部分即可
// 5. dp[i](在前面的拆分中的最大值)
dp[i]
);
}
}
return dp[n];
};