指尖划过的轨迹,藏着最细腻的答案~
题目:
给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:
- 子数组的长度是
k,且 - 子数组中的所有元素 各不相同 。
返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回 0 。
子数组 是数组中一段连续非空的元素序列。
示例 1:
输入: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:
输入:nums = [4,4,4], k = 3
输出:0
解释:nums 中长度为 3 的子数组是:
- [4,4,4] 不满足全部条件,因为元素 4 出现重复。
因为不存在满足全部条件的子数组,所以返回 0 。
提示:
分析:
定长滑动窗口一般分为三步走:
- 进入窗口:将当前值累加到窗口和
sum;由于我们从下标0开始遍历,因此在第一个窗口全部遍历完成之前,我们不应该进行第二步与第三步; - 更新答案:本题要求的是窗口中不相同数的数目,我们可以使用一个哈希表存储窗口中的数字,哈希表的长度
size就是不同数字的数量;如果size == k即满足题意,更新答案; - 离开窗口:最左边的值此时已经超过了窗口的数量限制,将其从窗口中删除,同时同步更新哈希表。
AC代码:
class Solution {
public:
long long maximumSubarraySum(vector<int>& nums, int k) {
long long ans = 0, sum = 0;
unordered_map<int, int> mp;
for (int i = 0; i < nums.size(); i++) {
// 1. 进入窗口
sum += nums[i];
mp[nums[i]]++;
int left = i - k + 1;
if (left < 0) {
continue;
}
// 2. 更新答案
if (mp.size() == k) {
ans = max(ans, sum);
}
// 3. 离开窗口
int out = nums[left];
sum -= out;
if (--mp[nums[left]] == 0) {
mp.erase(nums[left]);
}
}
return ans;
}
};