【动态规划】LeetCode343. 整数拆分 -Medium

267 阅读1分钟

题目

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。

示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

说明: 你可以假设 n 不小于 2 且不大于 58。

动态规划四步走

1. 定义状态
2. 初始状态
3. 状态转移方程
4. 从dp[]中获取结果

具体到题目

定义状态

定义dp[i]为数字i拆分的最大乘积

初始状态

dp[0] = 0;
dp[1] = 0;

状态转移方程

以数字5为例,可以至少可以分解成1+4,因此对于数字n,至少可以分解得到的乘积为n-1;

遍历2到n/2向上取整,每个分解的数取指针j和dp[j]的最大值,另一部分就是n-j或者dp[n-j]的最大值,此时的乘积就是取j的乘积。

let res= n-1
for(let j=2;j<= Math.ceil(n/2),j++)
	cur = max(j,dp[j])*max(n-j,dp[n-j])
    res = cur > res ? cur: res;
dp[n] = res

完整代码

var integerBreak = function (n) {
  if (typeof n !== 'number' || n < 2) {
    return;
  }
  const dp = new Array(n + 1).fill(0);
  dp[0] = 0;
  dp[1] = 0;
  for (let i = 2; i <= n; i++) {
    let res = i - 1;
    for (let j = 1; j <= Math.ceil(i / 2); j++) {
      const k = i - j;
      const cur = Math.max(j, dp[j]) * Math.max(k, dp[k]);
      if (cur > res) {
        res = cur;
      }
    }
    dp[i] = res;
  }
  console.log(dp);
  return dp[n];
};

总结

数学找规律题,自底向上分析就可以得到复用关系