LC-6230.长度为K子数组中的最大和

题目描述

leetcode 中等题

给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:

子数组的长度是 k,且
子数组中的所有元素 各不相同 。
返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回 0 。

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

示例1:

1
2
3
4
5
6
7
8
9
输入:nums = [1,5,4,2,9,9,9], k = 3
输出:15
解释:nums 中长度为 3 的子数组是:
- [1,5,4] 满足全部条件,和为 10
- [5,4,2] 满足全部条件,和为 11
- [4,2,9] 满足全部条件,和为 15
- [2,9,9] 不满足全部条件,因为元素 9 出现重复。
- [9,9,9] 不满足全部条件,因为元素 9 出现重复。
因为 15 是满足全部条件的所有子数组中的最大子数组和,所以返回 15

示例2:

1
2
3
4
5
输入:nums = [4,4,4], k = 3
输出:0
解释:nums 中长度为 3 的子数组是:
- [4,4,4] 不满足全部条件,因为元素 4 出现重复。
因为不存在满足全部条件的子数组,所以返回 0

提示:

1
2
1 <= k <= nums.length <= 1e5
1 <= nums[i] <= 1e5

分析

滑动窗口的时间复杂度只有 O(N),因为不管嵌套了几次内层循环,左右指针都是单调的从 0 -> (n - 1) 递增,即总共的循环次数只会有 n 次,所以时间复杂度是满足题目的数据范围要求的。

滑动窗口 + Set

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
class Solution {
public long maximumSubarraySum(int[] nums, int k) {
Set<Integer> exist = new HashSet<>();
int n = nums.length;
long ans = 0;
long curSum = 0;
for(int i = 0, j = 0; i < n && j < n; j++){
int rightItem = nums[j];
while(exist.contains(rightItem)){
// 存在重复元素, 移动左指针,直到重复元素被移除了
exist.remove(nums[i]);
curSum -= nums[i++];
}
curSum += rightItem;
exist.add(rightItem);
if(exist.size() > k){
exist.remove(nums[i]);
curSum -= nums[i++];
}
if(exist.size() == k){
ans = Math.max(ans, curSum);
}
}
return ans;
}
}
  • 时间复杂度:O(N):左右指针单调的从 0->(n - 1) 递增,循环次数总共只会有 n
  • 空间复杂度:O(K)

滑动窗口 + Map

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
class Solution {
public long maximumSubarraySum(int[] nums, int k) {
Map<Integer, Integer> cnt = new HashMap<>();
int n = nums.length;
long ans = 0;
long curSum = 0;
for(int j = 0; j <= k - 1; j++){
cnt.put(nums[j], cnt.getOrDefault(nums[j], 0) + 1);
curSum += nums[j];
}
if(cnt.size() == k){
ans = Math.max(ans, curSum);
}
for(int i = 1, j = k; j < n; i++, j++){
curSum -= nums[i - 1];
int value = cnt.get(nums[i - 1]);
if(value == 1){
cnt.remove(nums[i - 1]);
}else{
cnt.put(nums[i - 1], value - 1);
}
curSum += nums[j];
cnt.put(nums[j], cnt.getOrDefault(nums[j], 0) + 1);
if(cnt.size() == k){
ans = Math.max(ans, curSum);
}
}
return ans;
}
}
  • 时间复杂度:O(N)
  • 空间复杂度:O(K)

LC-6230.长度为K子数组中的最大和
https://wecgwm.github.io/2022/11/06/LC-6230-长度为K子数组中的最大和/
作者
yichen
发布于
2022年11月6日
许可协议