文章目录
题目
标题和出处
标题:删除子数组的最大得分
难度
5 级
题目描述
要求
给定一个正整数数组 nums \texttt{nums} nums,需要从中删除一个含有不同元素 的子数组。删除子数组的得分 是子数组各元素之和。
返回只删除一个 子数组可获得的最大得分。
如果数组 b \texttt{b} b 是数组 a \texttt{a} a 的一个连续子序列,即如果它等于 a[l],a[l+1],...,a[r] \texttt{a[l],a[l+1],...,a[r]} a[l],a[l+1],...,a[r],那么它就是 a \texttt{a} a 的一个子数组。
示例
示例 1:
输入: nums = [4,2,4,5,6] \texttt{nums = [4,2,4,5,6]} nums = [4,2,4,5,6]
输出: 17 \texttt{17} 17
解释:最优子数组是 [2,4,5,6] \texttt{[2,4,5,6]} [2,4,5,6]。
示例 2:
输入: nums = [5,2,1,2,5,2,1,2,5] \texttt{nums = [5,2,1,2,5,2,1,2,5]} nums = [5,2,1,2,5,2,1,2,5]
输出: 8 \texttt{8} 8
解释:最优子数组是 [5,2,1] \texttt{[5,2,1]} [5,2,1] 或 [1,2,5] \texttt{[1,2,5]} [1,2,5]。
数据范围
- 1 ≤ nums.length ≤ 10 5 \texttt{1} \le \texttt{nums.length} \le \texttt{10}^\texttt{5} 1≤nums.length≤105
- 1 ≤ nums[i] ≤ 10 4 \texttt{1} \le \texttt{nums[i]} \le \texttt{10}^\texttt{4} 1≤nums[i]≤104
解法
思路和算法
由于数组 nums \textit{nums} nums 中的元素都是正整数,因此对于任意子数组,在子数组的任意一端添加元素(即增加子数组的长度)后子数组中的元素和一定增加,在子数组的任意一端删除元素(即减少子数组的长度)后子数组中的元素和一定减少。为了使删除子数组的得分最大,应该使子数组尽可能长。
考虑数组 nums \textit{nums} nums 的两个不同下标 end 1 \textit{end}_1 end1 和 end 2 \textit{end}_2 end2,其中 end 1 < end 2 \textit{end}_1 < \textit{end}_2 end1<end2,分别以这两个下标作为结束下标,寻找元素各不相同的最长子数组,将这两个最长子数组的开始下标分别记为 start 1 \textit{start}_1 start1 和 start 2 \textit{start}_2 start2,则必有 start 1 ≤ start 2 \textit{start}_1 \le \textit{start}_2 start1≤start2(否则对于任意 start 2 ≤ start 3 < start 1 \textit{start}_2 \le \textit{start}_3 < \textit{start}_1 start2≤start3<start1,下标范围 [ start 3 , end 1 ] [\textit{start}_3, \textit{end}_1] [start3,end1] 的子数组的元素各不相同,且长度大于下标范围 [ start 1 , end 1 ] [\textit{start}_1, \textit{end}_1] [start1,end1] 的子数组)。
因此,可以使用变长滑动窗口寻找数组 nums \textit{nums} nums 中的以每个下标作为结束下标的元素各不相同的最长子数组。用 [ start , end ] [\textit{start}, \textit{end}] [start,end] 表示滑动窗口,初始时 start = end = 0 \textit{start} = \textit{end} = 0 start=end=0。将滑动窗口的右端点 end \textit{end} end 向右移动,移动过程中维护滑动窗口的左端点 start \textit{start} start,对于每个 end \textit{end} end 寻找元素各不相同的最大滑动窗口。
为了判断滑动窗口中是否有重复元素,需要使用哈希集合存储滑动窗口中出现的元素。用 sum \textit{sum} sum 表示滑动窗口中的元素和。对于每个右端点 end \textit{end} end,将右端点处的元素记为 num = nums [ end ] \textit{num} = \textit{nums}[\textit{end}] num=nums[end],执行如下操作。
-
将 sum \textit{sum} sum 的值增加 num \textit{num} num。
-
如果哈希集合中有元素 num \textit{num} num,则滑动窗口 [ start , end ] [\textit{start}, \textit{end}] [start,end] 中有两个元素 num \textit{num} num,因此将 sum \textit{sum} sum 的值减去 nums [ start ] \textit{nums}[\textit{start}] nums[start],从哈希集合中移除元素 nums [ start ] \textit{nums}[\textit{start}] nums[start],然后将 start \textit{start} start 向右移动一位,重复该操作直到哈希集合中没有元素 num \textit{num} num。
-
当前滑动窗口 [ start , end ] [\textit{start}, \textit{end}] [start,end] 中的子数组为以 end \textit{end} end 作为结束下标的元素各不相同的最长子数组,其元素和为 sum \textit{sum} sum。使用 sum \textit{sum} sum 更新最大得分。
遍历结束之后,即可得到删除子数组的最大得分。
代码
java
class Solution {
public int maximumUniqueSubarray(int[] nums) {
Set<Integer> set = new HashSet<Integer>();
int maxSum = 0;
int sum = 0;
int start = 0, end = 0;
int length = nums.length;
while (end < length) {
int num = nums[end];
sum += num;
while (set.contains(num)) {
sum -= nums[start];
set.remove(nums[start]);
start++;
}
set.add(num);
maxSum = Math.max(maxSum, sum);
end++;
}
return maxSum;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。滑动窗口的左右端点最多各遍历数组 nums \textit{nums} nums 一次。
-
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。空间复杂度主要取决于哈希集合,哈希集合中每个元素最多出现一次。