leetcode
leetcode 1101 ~ 1150
删除一次得到子数组最大和

删除一次得到子数组最大和

难度:

标签:

题目描述

代码结果

运行时间: 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] 作为一种可能?
在状态转移方程 dp1[i] = max(dp1[i-1] + arr[i], dp0[i-1]) 中,选项 dp0[i-1] 代表的是在第 i-1 位置结束的最大子数组和且没有删除任何元素的情况。当我们考虑 dp1[i] 的值时,我们的目标是考虑到删除一个元素的情况。如果选择 dp0[i-1] + arr[i],这将违反只删除一个元素的原则,因为这样会意味着从 i-1 开始没有删除元素并且包括 i 在内,即不删除任何元素。因此,dp0[i-1] 是在不包括 arr[i] 的情况下最大的可能子数组和,这正是我们通过删除 arr[i] 之前的元素(如果需要)到达此状态的含义。
🦆
对于 dp0 的状态更新公式 dp0[i] = max(dp0[i-1], 0) + arr[i],请问为什么这里选择加0而不是保持 dp0[i-1] 的值?
在 dp0 的状态更新公式 dp0[i] = max(dp0[i-1], 0) + arr[i] 中,使用 max(dp0[i-1], 0) 是为了处理子数组的非负起始条件。如果 dp0[i-1] 是负数,继续累加这个负数将会减少总和,不利于获取最大子数组和。因此,如果 dp0[i-1] 为负,重新开始计算子数组和从当前元素 arr[i] 开始,这是因为从当前元素开始可能得到更大的子数组和。
🦆
在给定的解法中,dp1 初始化为0是基于什么考虑?这是否意味着在第一次迭代中,删除操作总是假设删除了第一个元素?
在给定的解法中,dp1 初始化为0实际上是基于考虑到在数组的开始位置,没有实际删除任何元素的情况。这意味着在第一次迭代中,删除操作假设的是可以删除第一个元素,但在实际计算中,由于第一个元素在 dp0 已经被计算,dp1 的初始值为0表示在没有删除任何元素的情况下的初始状态。这是为了确保 dp1 在初始状态能够正确地反映删除一个元素的情况。
🦆
在所有示例中,最终结果 res 是如何确保在只删除一个元素的情况下始终返回最优解的?
在解法中,最终结果 res 是在每一步迭代中同时考虑并更新 dp0[i] 和 dp1[i] 的最大值。dp0[i] 考虑的是不删除任何元素的最大子数组和,而 dp1[i] 考虑的是删除一个元素的情况。通过在每个 i 的位置更新 res 为 dp0[i] 和 dp1[i] 的最大值,我们确保了 res 在只删除一个元素的情况下始终是最优的,因为它实时地跟踪并比较了两种情况的最大可能值。

相关问题