关键
我认为滑动窗口的核心其实是 入-更新-出的过程
更新本质上也就是一个数学中的函数
特别需要注意的就是窗口大小不足的时候需要continue来进入窗口
class Solution {
public:
int maxVowels(string s, int k) {
int ans = 0, vowel = 0;
for (int i = 0; i < s.length(); i++) {
// 1. 进入窗口
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') {
vowel++;
}
if (i < k - 1) { // 窗口大小不足 k
continue;
}
// 2. 更新答案
ans = max(ans, vowel);
// 3. 离开窗口
char out = s[i - k + 1];
if (out == 'a' || out == 'e' || out == 'i' || out == 'o' || out == 'u') {
vowel--;
}
}
return ans;
}
};
典型题目
https://leetcode.cn/problems/maximum-sum-of-distinct-subarrays-with-length-k/description/
这道题目需要维护一个目前在窗口中的元素的类型数目,最开始我使用的是set来实现,每次在其中insert元素,但是在删除元素是并没有注意元素数目,比如面对9 9 9 1 2 3 k = 3 的这种情况下,当i = 1 ,会直接删除9
我其实在思考能不能使用更加好的方式来存储,思考了set,已经排除了,vec不方便,map可以很方便的改变key的值,pair配合vec,感觉不如map方便
class Solution {
public:
long long maximumSubarraySum(vector<int>& nums, int k) {
std::map<int,int> s; //如何处理连续的相同数字串 比如 999123
long long max = 0;
long long cnt = 0;
for (int i = 0; i< nums.size(); i++)
{
s[nums[i]]++;;
cnt += nums[i];
if (i < k - 1)
continue;
if (s.size() == k)
max = std::max(cnt, max);
cnt -= nums[i - k + 1];
if (s[nums[i - k + 1]] != 1)
s[nums[i - k + 1]]--;
else
s.erase(nums[i - k + 1]);
}
return max;
}
};
https://leetcode.cn/problems/minimum-recolors-to-get-k-consecutive-black-blocks/
逆向思维即可
class Solution {
public:
int minimumRecolors(string blocks, int k) {
int cnt = 0, ans = INT32_MAX;
for (int i = 0; i < blocks.size(); i++)
{
if (blocks[i] == 'W')
cnt++;
if (i < k - 1)
continue;
ans = std::min(cnt, ans);
// std::cout << ans << " " << cnt << "#" << std::endl;
if (blocks[i - k + 1] == 'W')
cnt--;
}
return ans;
}
};