题目
给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组。删除子数组的 得分 就是子数组各元素之 和 。
返回 只删除一个 子数组可获得的 最大得分 。
如果数组 b 是数组 a 的一个连续子序列,即如果它等于 a[l],a[l+1],...,a[r] ,那么它就是 a 的一个子数组。
跳转链接:LeetCode1695
解析
本题要求从一个数组中取出连续的和最大的无重复数组,所以我们可以考虑使用滑动窗口。
解法一
使用Set来判断窗口中是否会有重复的元素,当有重复的元素出现时,从左侧(left)开始依次删除元素,直到将左侧的重复元素删除,然后将右侧的重复元素加入窗口中。每添加一个元素后,ans取ans和sum中的较大值,这样可以保证最终得到的结果是最大的。
public class Solution {
public int maximumUniqueSubarray(int[] nums) {
Set<Integer> set = new HashSet<>();
//left用于标记窗口的最左侧元素的下标
//sum用于记录当前窗口包含元素的和
int ans = 0, sum = 0, left = 0;
//从第一个元素开始依次加入窗口
for (int num : nums) {
//当出现重复的元素时,从窗口的左侧依次删除元素,直到删去左侧的重复元素
while(set.contains(num)){
set.remove(nums[left]);
sum -= nums[left];
left++;
}
//将元素加入窗口
set.add(num);
sum += num;
ans = Math.max(ans, sum);
}
return ans;
}
}
解法二
使用Set来解题的话耗时较高,考虑到本题的数据范围,可以直接使用boolean数组来判断窗口中是否存在该元素。
public class Solution {
public int maximumUniqueSubarray(int[] nums) {
//用于判断窗口中是否存在该元素,当存在时以该元素的值为下标的boolean取值为true
boolean[] use = new boolean[100005];
//left用于标记窗口的最左侧元素的下标
//sum用于记录当前窗口包含元素的和
int ans = 0, sum = 0, left = 0;
for (int num : nums) {
//当出现重复的元素时,从窗口的左侧依次删除元素,直到删去左侧的重复元素
while(use[num]){
use[nums[left]] = false;
sum -= nums[left];
left++;
}
//将元素加入窗口
use[num] = true;
sum += num;
ans = Math.max(ans, sum);
}
return ans;
}
}
376

被折叠的 条评论
为什么被折叠?



