Problem
You are given an integer array nums.
You can do the following operation on the array at most once:
- Choose any integer xsuch thatnumsremains non-empty on removing all occurrences ofx.
- Remove all occurrences of xfrom the array.
Return the maximum subarray sum across all possible resulting arrays.
A subarray is a contiguous non-empty sequence of elements within an array.
https://leetcode.com/problems/maximize-subarray-sum-after-removing-all-occurrences-of-one-element/
Example 1:
Input:
nums = [-3,2,-2,-1,3,-2,3]
Output:7
Explanation:
We can have the following arrays after at most one operation:
- The original array is
nums = [-3, 2, -2, -1,3, -2, 3]. The maximum subarray sum is3 + (-2) + 3 = 4.- Deleting all occurences of
x = -3results innums = [2, -2, -1,3, -2, 3]. The maximum subarray sum is3 + (-2) + 3 = 4.- Deleting all occurences of
x = -2results innums = [-3,2, -1, 3, 3]. The maximum subarray sum is2 + (-1) + 3 + 3 = 7.- Deleting all occurences of
x = -1results innums = [-3, 2, -2,3, -2, 3]. The maximum subarray sum is3 + (-2) + 3 = 4.- Deleting all occurences of
x = 3results innums = [-3,2, -2, -1, -2]. The maximum subarray sum is 2.The output is
max(4, 4, 7, 4, 2) = 7.
Example 2:
Input:
nums = [1,2,3,4]
Output:10
Explanation:
It is optimal to not perform any operations.
Constraints:
- 1 <= nums.length <= 10⁵
- -10⁶ <= nums[i] <= 10⁶
Test Cases
| 1 | class Solution: | 
| 1 | import pytest | 
Thoughts
系列问题:
- 53. Maximum Subarray 普通的最大 subarray 问题
- 1186. Maximum Subarray Sum with One Deletion 允许最多删除一个位置的数字
本题是允许最多删除一个数字的所有 occurrences。
显然只有删掉某个负数,才有可能得到更大的最大子数组。
如果直接 遍历每个负数,计算其所有 occurrences 被删掉之后的最大子数组,时间复杂度是 O(n²),肯定会超时。这里有大量的重复计算。
沿用前两题中 第二种 DP 的定义,ps(i) = Σnums[0...i] 和 low(i)(nums[0...i] 的(小于等于零的)最小前缀和)。调整 low2(i) 的含义为 arr[0...i] 的(小于等于零的)最小前缀和再加上额外被删掉的数字的所有 occurrences 所能得到的最小值(在 ps(i) 中减去此值,就是以 i 为右端点但是删掉至多一个数字的所有 occurrences 之后的最大 subarray 和)。
在 problem 1186 中只允许删除一个位置的数字,low2 的状态转移为:
其中  对应了删掉 arr[i](那就至少保留 arr[i-1])的情况。但在本题,如果删除 arr[i] = v,则还需要删掉 i 左边其他的 v。也就是 low(i - 2) 对应的子数组右边的其他 v 也要加上去。用一个关于 v 的字典来记录这个信息:
其中 j 是 i 左边的最靠右的值为 v 的位置。这里有个小技巧是并没有刻意记录有几个 v 需要删掉,而是记录上一次遇见 v 的时候,需要从 ps 里减去的值是多少。
这样本题的 low2 的状态转移为:
时间复杂度 O(n),空间复杂度 O(n)。
Code
| 1 | from collections import defaultdict |