题目链接
3487. 删除后的最大子数组元素和 - 力扣(LeetCode)
题目描述
给你一个整数数组 nums 。
你可以从数组 nums 中删除任意数量的元素,但不能将其变为 空 数组。执行删除操作后,选出 nums 中满足下述条件的一个子数组:
- 子数组中的所有元素 互不相同 。
- 最大化 子数组的元素和。
返回子数组的 最大元素和 。
子数组 是数组的一个连续、非空 的元素序列。
题目示例
示例 1 :
java
输入:nums = [1,2,3,4,5]
输出:15
解释:
不删除任何元素,选中整个数组得到最大元素和。
示例 2 :
java
输入:nums = [1,1,0,1,1]
输出:1
解释:
删除元素 nums[0] == 1、nums[1] == 1、nums[2] == 0 和 nums[3] == 1 。选中整个数组 [1] 得到最大元素和。
解题思路
- 问题理解:题目要求计算数组中所有不重复的非负数的和。如果数组中全是负数,则返回最大的负数。
- 核心思路 :
- 使用一个
HashSet来记录已经处理过的非负数,确保每个非负数只被累加一次。 - 遍历数组,对每个元素进行分类处理:
- 如果是负数,更新当前最大的负数。
- 如果是非负数且未被处理过(即
set.add(x)返回true),则将其累加到sum中。
- 最后检查
set是否为空:- 如果为空,说明数组中没有非负数,返回最大的负数。
- 否则,返回非负数的累加和。
- 使用一个
- 关键点 :
- 利用
HashSet的去重特性确保非负数只被累加一次。 - 通过
mx变量动态维护最大的负数,以处理全为负数的情况。
- 利用
题解代码
java
class Solution {
public int maxSum(int[] nums) {
// 使用HashSet来记录已经处理过的非负数
Set<Integer> set = new HashSet<>();
// sum用于累加所有不重复的非负数
int sum = 0;
// mx用于记录最大的负数(如果所有数都是负数时使用)
int mx = Integer.MIN_VALUE;
// 遍历数组中的每个元素
for(int x : nums){
if(x < 0){
// 如果是负数,更新最大的负数
mx = Math.max(mx, x);
} else if (set.add(x)){
// 如果是非负数且未被处理过(set.add(x)返回true表示成功添加)
// 则将其加入sum
sum += x;
}
}
// 如果set为空(说明所有数都是负数),返回最大的负数
// 否则返回非负数的和
return set.isEmpty() ? mx : sum;
}
}
复杂度分析
- 时间复杂度 :
- 遍历数组的时间复杂度为
O(n),其中n是数组的长度。 HashSet的插入操作set.add(x)的平均时间复杂度为O(1)。- 因此,总的时间复杂度为
O(n)。
- 遍历数组的时间复杂度为
- 空间复杂度 :
HashSet在最坏情况下需要存储所有非负数,因此空间复杂度为O(n)(例如所有数都是非负数且不重复时)。- 其他变量(如
sum、mx)占用常数空间,可以忽略。