integerBreak

leetcode算法篇,常见算法总结

leetcode算法之动态规划

整数拆分More info: leetcode343

题目描述

给定一个正整数 n,你需要将它拆分成至少两个正整数的和,并且你可以将这些整数进行重新组合(即:我们可以将它们相加、相乘等操作),以便使它们的乘积最大化。你需要找到最大的乘积,并返回这个乘积。
该问题的解决思路可以通过动态规划来解决。具体来说

1
2
3
4
5
6
7
8
9
10
11
1、定义状态:设 dp[i] 为整数 i 的最大乘积分割。

2、初始化状态:对于 dp[1] 来说,因为 1 不能分割成两个数之和,所以 dp[1] = 0

3、状态转移:对于整数 i,我们可以尝试将其分割成两个整数 j 和 i - j,然后分别计算 j 和 i - j 的最大乘积分割并相乘。同时,我们还需要考虑 j 和 i - j 本身作为乘积,这样我们可以从 dp[j] 和 dp[i - j] 中取最大值。也就是说,状态转移公式是:

4、dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j])) (对于 1 <= j <= i - 1

循环求解:通过循环从 2 到 n,逐步计算 dp[i],以得到 dp[n]。

通过这个动态规划算法,你可以找到最大的乘积分割。通过递推计算 dp 数组中的值,你就可以得到整数 n 拆分后的最大乘积。

具体实现

为了在JavaScript中实现整数拆分问题,你可以使用动态规划的方式。具体来说,你可以使用一个数组 dp 来存储整数 i 的最大乘积分割值。然后通过循环从 2 到 n,逐步计算 dp[i]。在每一步中,你尝试将 i 分割成两个整数 j 和 i - j,并计算可能的最大乘积。最终 dp[n] 就是你想要的答案。下面是一个示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function integerBreak(n) {
// 创建一个数组 dp 用来存储整数 i 的最大乘积
const dp = new Array(n + 1).fill(0);

// dp[1] = 0,因为 1 不能被分割成两个正整数
dp[1] = 0;

// 循环计算 dp[i],从 2 到 n
for (let i = 2; i <= n; i++) {
// 对于每一个整数 i,尝试将其分割成两个整数 j 和 i - j
for (let j = 1; j <= i - 1; j++) {
// 计算两种情况:j * (i - j) 和 j * dp[i - j]
dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]);
}
}

// 返回整数 n 的最大乘积分割
return dp[n];
}

// 测试
console.log(integerBreak(10)); // 输出 36

分析总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
**如何理解** dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]);

为了理解 dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]) 这个状态转移方程,让我们逐步分解并解释它:
问题描述:dp[i] 是表示整数 i 的最大乘积的数组。我们要找到 i 拆分为至少两个正整数之和后,这些整数的乘积的最大值。

尝试分割:我们尝试将整数 i 分割成两个整数 j 和 i - j。通过遍历 j 的值从 1 到 i - 1,我们可以遍历所有可能的分割情况。

两种计算方式:

直接乘积:j * (i - j) 是将 i 直接分割成两个整数 j 和 i - j,然后计算它们的乘积。这种情况下不涉及递归计算。

递归乘积:j * dp[i - j] 是使用动态规划数组 dp 来计算的。这里,dp[i - j] 表示整数 i - j 的最大乘积。我们将整数 j 乘以 dp[i - j] 得到一种分割 i 的情况的乘积。这种情况下利用了之前的计算结果。

取最大值:通过 Math.max(dp[i], j * (i - j), j * dp[i - j]),我们取当前 dp[i] 与这两种情况的乘积的最大值。这样,我们能够更新 dp[i],使其始终保持当前计算到的整数 i 的最大乘积。

总之,dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]) 这个状态转移方程的意思是,在当前 i 的情况下,尝试分割 i 为两个整数 j 和 i - j,计算这两种情况的乘积,并取这些乘积和当前 dp[i] 中的最大值来更新 dp[i]。通过这种方式,动态规划数组 dp 最终存储了从 1 到 n 的最大乘积。

integerBreak
https://zbdev.online/2024/02/17/integerBreak/
作者
zzb
发布于
2024年2月17日
许可协议