问题描述
小R遇到一个数组 nums,他需要从中找到两个非重叠的子数组,它们的长度分别为 firstLen 和 secondLen。这两个子数组可以相互独立,顺序没有限制,但它们不能有任何重叠。你需要帮小R找出这些子数组的最大和。
测试样例
样例1:
输入:
nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2
输出:20
样例2:
输入:
nums = [3,8,1,3,5,2,1,0], firstLen = 3, secondLen = 2
输出:21
样例3:
输入:
nums = [2,1,4,3,5,9,5,0,3,8], firstLen = 4, secondLen = 3
输出:33
分析
这个函数 solution 的目的是找到两个不重叠子数组的最大和,其中第一个子数组的长度为 firstLen,第二个子数组的长度为 secondLen。下面是对这个函数的详细思路分析:
总体思路
- 前缀和计算:首先通过前缀和数组
cum_sum来快速计算任意区间的和。 - 动态规划:使用动态规划来分别计算两个子数组的最大和,并将它们存储在
dp数组中。 - 合并结果:最后通过遍历所有可能的位置,找到两个不重叠子数组的最大和。
具体步骤
1. 前缀和计算
- 创建一个长度为
nums.length + 1的数组cum_sum,初始化为0。 - 遍历
nums数组,填充cum_sum数组,使得cum_sum[i]表示nums数组从第0个元素到第i-1个元素的和。
2. 动态规划
- 创建一个二维数组
dp,其中dp[0]和dp[1]分别用于存储第一个子数组和第二个子数组的最大和。 - 初始化
dp数组的所有值为0。
-
计算第一个子数组的最大和:
- 对于每个位置
i,更新dp[0][i]为前firstLen个元素的最大和。
- 对于每个位置
for (let i = firstLen; i <= nums.length; i++) {
dp[0][i] = Math.max(dp[0][i - 1], cum_sum[i] - cum_sum[i - firstLen]);
}
Copy
-
计算第二个子数组的最大和:
- 对于每个位置
i,更新dp[1][i]为前secondLen个元素的最大和。
- 对于每个位置
for (let i = secondLen; i <= nums.length; i++) {
dp[1][i] = Math.max(dp[1][i - 1], cum_sum[i] - cum_sum[i - secondLen]);
}
3. 合并结果
-
遍历所有可能的位置
i,找到两个不重叠子数组的最大和。- 对于每个位置
i,计算dp[0][i]加上从i到i + secondLen的和。 - 对于每个位置
i,计算dp[1][i]加上从i到i + firstLen的和。
- 对于每个位置
for (let i = firstLen; i <= nums.length - secondLen; i++) {
max_sum = Math.max(max_sum, dp[0][i] + (cum_sum[i + secondLen] - cum_sum[i]));
}
for (let i = secondLen; i <= nums.length - firstLen; i++) {
max_sum = Math.max(max_sum, dp[1][i] + (cum_sum[i + firstLen] - cum_sum[i]));
}
代码详解
涉及到的知识点
- 前缀和:通过前缀和数组
cum_sum快速计算任意区间的和。 - 动态规划:使用动态规划方法来分别计算两个子数组的最大和。
- 数组操作:创建和操作数组,包括初始化、填充和遍历。
- 条件判断:使用
if语句来控制程序流程。 - 循环结构:使用
for循环来遍历数组。 - 函数定义与调用:定义函数并调用它。
- 测试用例:编写测试用例来验证函数的正确性。
总结
通过青训营豆包MarsCode AI刷题,我学到了如何高效地运用多种算法和数据结构来解决实际问题。在前缀和的应用中,我掌握了快速计算数组中任意区间元素和的方法,极大地提高了算法效率。动态规划让我学会了如何定义状态、递推方程以及边界条件,从而有效解决优化问题。在数组操作方面,我熟练掌握了初始化、填充和遍历等基础操作,为解决大多数算法问题打下了坚实的基础。同时,通过条件判断和循环结构,我能够更好地控制程序的执行流程,解决复杂的逻辑问题。在函数定义与调用方面,我学会了如何合理地组织代码结构,提高代码的可读性和可维护性。最后,通过编写有效的测试用例,我能够验证算法的正确性,确保其在不同场景下的表现。总的来说,青训营的学习不仅提升了我的技术能力,还培养了我的问题分析和解决能力,希望我能学到更多的知识,提升自己。