[LeetCode] 1695. Maximum Erasure Value

You are given an array of positive integers nums and want to erase a subarray containing unique elements. The score you get by erasing the subarray is equal to the sum of its elements.

Return the maximum score you can get by erasing exactly one subarray.

An array b is called to be a subarray of a if it forms a contiguous subsequence of a, that is, if it is equal to a[l],a[l+1],...,a[r] for some (l,r).

Example 1:

Input: nums = [4,2,4,5,6]
Output: 17
Explanation: The optimal subarray here is [2,4,5,6].

Example 2:

Input: nums = [5,2,1,2,5,2,1,2,5]
Output: 8
Explanation: The optimal subarray here is [5,2,1] or [1,2,5].

Constraints:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 104

删除子数组的最大得分。

给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组。删除子数组的 得分 就是子数组各元素之 和 。

返回 只删除一个 子数组可获得的 最大得分 。

如果数组 b 是数组 a 的一个连续子序列,即如果它等于 a[l],a[l+1],...,a[r] ,那么它就是 a 的一个子数组。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-erasure-value
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路是滑动窗口,而且跟 第三题 很接近。这里我们找的是一个子数组的和,子数组的数字们都是互不相同的,我们用 hashset 来检查窗口内部的元素是否有重复。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public int maximumUniqueSubarray(int[] nums) {
 3         int start = 0;
 4         int end = 0;
 5         int sum = 0;
 6         int res = 0;
 7         int len = nums.length;
 8         HashSet<Integer> set = new HashSet<>();
 9         while (end < len) {
10             if (!set.contains(nums[end])) {
11                 sum += nums[end];
12                 set.add(nums[end]);
13                 end++;
14                 res = Math.max(res, sum);
15             } else {
16                 sum -= nums[start];
17                 set.remove(nums[start]);
18                 start++;
19             }
20         }
21         return res;
22     }
23 }

 

这里我再提供一个用数组当做 hashset 的实现,思路是一样的,但是运行速度快很多。

 1 class Solution {
 2     public int maximumUniqueSubarray(int[] nums) {
 3         int start = 0;
 4         int end = 0;
 5         int len = nums.length;
 6         int sum = 0;
 7         int res = 0;
 8         int[] set = new int[10001];
 9         while (end < len) {
10             if (set[nums[end]] == 0) {
11                 sum += nums[end];
12                 set[nums[end]] = 1;
13                 end++;
14                 res = Math.max(res, sum);
15             } else {
16                 sum -= nums[start];
17                 set[nums[start]] = 0;
18                 start++;
19             }
20         }
21         return res;
22     }
23 }

 

这道题也可以用前缀和的思路实现。首先需要创建一个长度为 len + 1 的数组记录input数组的前缀和。也是需要左右两个指针,一开始右指针往前走,并同时将当前数字 nums[end] 及其下标的对应关系记录在hashmap里。当我们遇到一个 nums[end] 存在于 hashmap 的时候,我们需要开始挪动 start 指针,一直挪动到覆盖掉 nums[end] 第一次出现的 index + 1 为止。一个需要考虑的corner case是如果整个数组都没有重复数字,目标子数组的和就是整个数组的和。这也就是为什么这道题计算前缀和的部分跟别的题稍有不同的原因之一。

Java实现

 1 class Solution {
 2     public int maximumUniqueSubarray(int[] nums) {
 3         int len = nums.length;
 4         int[] sums = new int[len + 1];
 5         // sums[0] = nums[0];
 6         for (int i = 0; i < len; i++) {
 7             sums[i + 1] = sums[i] + nums[i];
 8         }
 9 
10         int res = 0;
11         HashMap<Integer, Integer> map = new HashMap<>();
12         int start = 0;
13         int end = 0;
14         while (end < len) {
15             if (map.containsKey(nums[end])) {
16                 res = Math.max(res, sums[end] - sums[start]);
17                 int lastIndex = map.get(nums[end]);
18                 while (start < lastIndex + 1) {
19                     map.remove(nums[start]);
20                     start++;
21                 }
22             }
23             map.put(nums[end], end);
24             end++;
25         }
26         // corner case, when end pointer keeps moving until the end of the array
27         res = Math.max(res, sums[end] - sums[start]);
28         return res;
29     }
30 }

 

相关题目

3. Longest Substring Without Repeating Characters

1695. Maximum Erasure Value

sliding window相关题目

LeetCode 题目总结

posted @ 2021-01-08 01:05  CNoodle  阅读(388)  评论(0编辑  收藏  举报