删除一次得到子数组最大和
难度:
标签:
题目描述
代码结果
运行时间: 71 ms, 内存: 24.1 MB
/*
* 思路:
* 1. 使用stream处理数组数据。
* 2. 使用Map数据结构存储当前最大值。
* 3. 迭代数组元素计算最大和。
*/
import java.util.stream.IntStream;
public int maximumSum(int[] arr) {
final int[] max = {arr[0]}; // 当前最大和
final int[] maxEndingHere = {arr[0]}; // 当前子数组的最大和
final int[] maxWithOneDeletion = {0}; // 允许删除一个元素的最大和
IntStream.range(1, arr.length).forEach(i -> {
maxWithOneDeletion[0] = Math.max(maxEndingHere[0], maxWithOneDeletion[0] + arr[i]);
maxEndingHere[0] = Math.max(maxEndingHere[0] + arr[i], arr[i]);
max[0] = Math.max(max[0], Math.max(maxEndingHere[0], maxWithOneDeletion[0]));
});
return max[0];
}
解释
方法:
本题解采用动态规划的方法来解决问题。定义两个状态:dp0[i] 表示不删除任何元素情况下,以 arr[i] 结尾的最大子数组总和;dp1[i] 表示删除一个元素情况下,以 arr[i] 结尾的最大子数组总和。状态转移方程为 dp1[i] = max(dp1[i-1] + arr[i], dp0[i-1]),它表示要么在前一个删除状态下继续加当前元素,要么从当前位置重新开始计算(删除前一个元素)。同时,dp0[i] = max(dp0[i-1], 0) + arr[i],表示当前位置的最大子数组和,可以选择加上当前元素或者从当前重新开始。最后结果 res 是在遍历过程中记录的 dp0[i] 和 dp1[i] 的最大值。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在动态规划的状态转移方程中,为什么 dp1[i] = max(dp1[i-1] + arr[i], dp0[i-1]) 选择使用 dp0[i-1] 而不是 dp0[i-1] + arr[i] 作为一种可能?
▷🦆
对于 dp0 的状态更新公式 dp0[i] = max(dp0[i-1], 0) + arr[i],请问为什么这里选择加0而不是保持 dp0[i-1] 的值?
▷🦆
在给定的解法中,dp1 初始化为0是基于什么考虑?这是否意味着在第一次迭代中,删除操作总是假设删除了第一个元素?
▷🦆
在所有示例中,最终结果 res 是如何确保在只删除一个元素的情况下始终返回最优解的?
▷