题目

给你一个整数数组 nums 和两个正整数 mk

请你返回 nums 中长度为 k几乎唯一 子数组的 最大和 ,如果不存在几乎唯一子数组,请你返回 0

如果 nums 的一个子数组有至少 m 个互不相同的元素,我们称它是 几乎唯一 子数组。

子数组指的是一个数组中一段连续 非空 的元素序列。

示例 1:

1
2
3
输入:nums = [2,6,7,3,1,7], m = 3, k = 4
输出:18
解释:总共有 3 个长度为 k = 4 的几乎唯一子数组。分别为 [2, 6, 7, 3] ,[6, 7, 3, 1] 和 [7, 3, 1, 7] 。这些子数组中,和最大的是 [2, 6, 7, 3] ,和为 18 。

示例 2:

1
2
3
输入:nums = [5,9,9,2,4,5,4], m = 1, k = 3
输出:23
解释:总共有 5 个长度为 k = 3 的几乎唯一子数组。分别为 [5, 9, 9] ,[9, 9, 2] ,[9, 2, 4] ,[2, 4, 5] 和 [4, 5, 4] 。这些子数组中,和最大的是 [5, 9, 9] ,和为 23 。

示例 3:

1
2
3
输入:nums = [1,2,1,2,1,2,1], m = 3, k = 3
输出:0
解释:输入数组中不存在长度为 k = 3 的子数组含有至少 m = 3 个互不相同元素的子数组。所以不存在几乎唯一子数组,最大和为 0 。

提示:

  • 1 <= nums.length <= 2 * 104
  • 1 <= m <= k <= nums.length
  • 1 <= nums[i] <= 109

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
public long maxSum(List<Integer> nums, int m, int k) {
HashMap<Integer ,Integer> map = new HashMap<>();
int n=nums.size();
long max=0;
long sum=0; // 注意要使用long型,否则越界
for(int i=0;i<n;i++){
sum+=nums.get(i);
if(map.containsKey(nums.get(i))){
map.put(nums.get(i),map.get(nums.get(i))+1);
}else{
map.put(nums.get(i),1);
}
if(i<k-1){
continue;
}
// System.out.printlni"map"+map.size());
if(sum>max&&map.size()>=m){
max=sum;
}
sum-=nums.get(i-(k-1));
if(map.get(nums.get(i-(k-1)))==1){
map.remove(nums.get(i-(k-1)));
}else{
map.put(nums.get(i-(k-1)),map.get(nums.get(i-(k-1)))-1);
}
//map.remove(i-(k-1));
}
return max;
}
}

知识点

思路:求子数组的 最大和是常规定长滑动窗口问题,这题对我来说难点在于如何判断唯一,我想到使用哈希表,它能保证键唯一。哈希表的键为该位置i的原数组的值,哈希表的值为该值在一个滑动窗口中出现的次数。