题目:
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例:
- 示例 1
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
- 示例 2
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明:
你可以假设 n 不小于 2 且不大于 58。
抛砖引玉
思路
拆成 n 个数,n 不固定
这种类型的题目:规则确定,起始条件不确定
- 动态规划
- 递归
动态规划
枚举 n,dp 记录不同 n 的结果值,dp[n]即查询结果:
- 确定拆分的整数个数: 2 < = i < = n 2<=i<=n 2<=i<=n
- dp[i]为 i 拆分的整数乘积最大值
- 拆分两个以上j,dp[i - j] -> dp[i - j]拆分两个即以上子集
- 拆分两个j,i-j
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function (n) {
let dp = Array(n + 1).fill(1)
for (let i = 2; i <= n; i++) {
let curMax = 0
for (let j = 1; j < i; j++) {
curMax = Math.max(curMax, Math.max(j * (i - j), j * dp[i - j]))
}
dp[i] = curMax
}
return dp[n]
}
递归
- 参数,要拆分的整数
- 终止条件:
- 遇到已经拆分过的数组
递归的逻辑基本和动态规划一致:
- 拆分一个数字j出来
- 属于的i-j可以独立作为一个数字,也可以继续拆分
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function (n) {
let dp = Array(n + 1).fill(1)
function dfs(n){
if (dp[n]) return dp[n];
let curMax = 0;
for (let i = 1; i < n; i++) {
curMax = Math.max(curMax, i * (n - i), i * dfs(n - i));
}
return dp[n] = curMax;
};
return dp[n]
}
优化的动态规划
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function (n) {
if (n < 4) return n - 1;
let dp = Array(n + 1).fill(1)
for (let i = 3; i <= n; i++) {
dp[i] = Math.max(Math.max(2 * (i - 2), 2 * dp[i - 2]), Math.max(3 * (i - 3), 3 * dp[i - 3]));
}
return dp[n];
}
题目:
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例:
- 示例 1
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
- 示例 2
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明:
你可以假设 n 不小于 2 且不大于 58。
抛砖引玉
思路
拆成 n 个数,n 不固定
这种类型的题目:规则确定,起始条件不确定
- 动态规划
- 递归
动态规划
枚举 n,dp 记录不同 n 的结果值,dp[n]即查询结果:
- 确定拆分的整数个数: 2 < = i < = n 2<=i<=n 2<=i<=n
- dp[i]为 i 拆分的整数乘积最大值
- 拆分两个以上j,dp[i - j] -> dp[i - j]拆分两个即以上子集
- 拆分两个j,i-j
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function (n) {
let dp = Array(n + 1).fill(1)
for (let i = 2; i <= n; i++) {
let curMax = 0
for (let j = 1; j < i; j++) {
curMax = Math.max(curMax, Math.max(j * (i - j), j * dp[i - j]))
}
dp[i] = curMax
}
return dp[n]
}
递归
- 参数,要拆分的整数
- 终止条件:
- 遇到已经拆分过的数组
递归的逻辑基本和动态规划一致:
- 拆分一个数字j出来
- 属于的i-j可以独立作为一个数字,也可以继续拆分
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function (n) {
let dp = Array(n + 1).fill(1)
function dfs(n){
if (dp[n]) return dp[n];
let curMax = 0;
for (let i = 1; i < n; i++) {
curMax = Math.max(curMax, i * (n - i), i * dfs(n - i));
}
return dp[n] = curMax;
};
return dp[n]
}
优化的动态规划
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function (n) {
if (n < 4) return n - 1;
let dp = Array(n + 1).fill(1)
for (let i = 3; i <= n; i++) {
dp[i] = Math.max(Math.max(2 * (i - 2), 2 * dp[i - 2]), Math.max(3 * (i - 3), 3 * dp[i - 3]));
}
return dp[n];
}
博客: 小书童博客
每天的每日一题,写的题解会同步更新到公众号一天一大 lee 栏目
欢迎关注留言
公号: 坑人的小书童