滑动窗口0x3f刷题
20250426
我正学着如何爱你
果然多做几遍我就会了,果然多复习几次我就会了
- 按照专题刷题,而不是随机刷题。同一个专题下的题目,套路是一样的,刷题效率杠杠滴~
- 螺旋上升式学习:先完成 1700 难度分以下的题目。把各个知识点的基础题刷一遍,再刷更难的题目。
滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
定长滑窗
入:下标为 i 的元素进入窗口,更新相关统计量。如果 i<k−1 则重复第一步。
更新:更新答案。一般是更新最大值/最小值。
出:下标为 i−k+1 的元素离开窗口,更新相关统计量。
索引 i 表示当前遍历到的字符串位置。
窗口的右边界是 i。
窗口的大小为 k,。
窗口的左边界是 i - k + 1。
因此窗口的范围是 [i - k + 1, i](闭区间)
请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。
class Solution {
public:
int maxVowels(string s, int k) {
int ans = 0,vowel = 0;
for(int i = 0;i < s.length();i++){
if(s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
vowel++;
if(i < k-1)continue;
ans = max(ans,vowel);
char out = s[i-k+1];
if(out == 'a' || out == 'e' || out == 'i' || out == 'o' || out == 'u')
vowel--;
}
return ans;
}
};
给出一个由 n 个元素组成的整数数组 nums 和一个整数 k 。
请找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k) {
int n = nums.size();
double sum = 0,ans = INT_MIN;
for(int i = 0;i < n;i++){
sum+=nums[i];
if(i < k - 1)continue;
ans = max(ans,sum/k);
sum-=nums[i-k+1];
}
return ans;
}
};
- 求最大值,则令max=INT_MIN;来赋初值
给你一个下标从 0 开始的数组 nums ,数组中有 n 个整数,另给你一个整数 k 。
半径为 k 的子数组平均值 是指:nums 中一个以下标 i 为 中心 且 半径 为 k 的子数组中所有元素的平均值,即下标在 i - k 和 i + k 范围(含 i - k 和 i + k)内所有元素的平均值。如果在下标 i 前或后不足 k 个元素,那么 半径为 k 的子数组平均值 是 -1 。
构建并返回一个长度为 n 的数组 avgs ,其中 avgs[i] 是以下标 i 为中心的子数组的 半径为 k 的子数组平均值 。
class Solution {
public:
vector<int> getAverages(vector<int>& nums, int k) {
long long sum = 0;
int n = nums.size();
vector<int> ans(n,-1);
for(int right = 0;right < n;right++){
sum += nums[right];//入
if(right<(2*k))continue;//定长窗口
ans[right-k]=sum/(2*k+1);//更新(right-k即为i)
sum-=nums[right-2*k];//出
}
return ans;
}
};
在下标i前或后不足k个元素时需要输出的是-1,所以可以直接先定义一个值为-1的数组再进行赋值- 明确了定长为2k+1,再明确需要
出的和入的对应数字即可
给你一个长度为 n 下标从 0 开始的字符串 blocks ,blocks[i] 要么是 'W' 要么是 'B' ,表示第 i 块的颜色。字符 'W' 和 'B' 分别表示白色和黑色。
给你一个整数 k ,表示想要 连续 黑色块的数目。
每一次操作中,你可以选择一个白色块将它 涂成 黑色块。
请你返回至少出现 一次 连续 k 个黑色块的 最少 操作次数。
- 解法一:
class Solution {
public:
// 转换为求:长度为K的窗口中,黑色块最多的个数
int minimumRecolors(string blocks, int k) {
const char BLACK = 'B';
int count = 0;
int maxCount = 0;
for (int i = 0; i < blocks.length(); i++) {
if (blocks[i] == BLACK) {count++;} //入
if (i < k - 1) {continue;}// 定长窗口
maxCount = max(maxCount, count);//更新最值
if (blocks[i - k + 1] == BLACK) {count--;}//出
}
return k - maxCount;
}
};
-
要使得操作次数最少,则需要定长窗口里的白色最少,即黑色最多,所以计算定长里black最多的cnt再用k减掉就得到了答案
-
解法二:
class Solution {
public:
int minimumRecolors(string blocks, int k) {
int cnt_w = 0;
for (int i = 0; i < k; i++) {
cnt_w += blocks[i] & 1;
}
int ans = cnt_w;
for (int i = k; i < blocks.length(); i++) {
cnt_w += (blocks[i] & 1) - (blocks[i - k] & 1);
ans = min(ans, cnt_w);
}
return ans;
}
};
- 使用位运算 (blocks[i] & 1) 判断字符是否为 'W':
- 如果字符是 'W',其 ASCII 值为 87,二进制最低位为 1,因此 (blocks[i] & 1) 结果为 1。
- 如果字符是 'B',其 ASCII 值为 66,二进制最低位为 0,因此 (blocks[i] & 1) 结果为 0。
- 把
if-else(或者?:三目运算符)写成s[i] & 1就会快很多(避免分支预测)
20250427
给你一个整数数组 nums 和两个正整数 m 和 k 。
请你返回 nums 中长度为 k 的 几乎唯一 子数组的 最大和 ,如果不存在几乎唯一子数组,请你返回 0 。
如果 nums 的一个子数组有至少 m 个互不相同的元素,我们称它是 几乎唯一 子数组。
子数组指的是一个数组中一段连续 非空 的元素序列。
class Solution {
public:
long long maxSum(vector<int>& nums, int m, int k) {
long long ans = 0,s = 0;
unordered_map<int, int> cnt;
for(int i = 0;i < nums.size();i++){
s += nums[i];
cnt[nums[i]]++;
int left = i - k + 1;
if(left < 0)continue;//定长窗口
if(cnt.size() >= m) ans = max(ans, s);//如果满足条件就更新最值
int out = nums[left];
s -= out;
if(--cnt[out] == 0)cnt.erase(out);
return ans;
}
};
- 哈希表用于记录出现次数
- 哈希表即键值对
命名键,递增值 - 用于
插删查 - 声明:
- `std::unordered_map<KeyType, ValueType> mapName;
- KeyType:键的类型。
- ValueType:值的类型。
- mapName:哈希表的名称`
- eg.
unordered_map<int, int> cnt;
- 插:
- mapName[key] = value;
- 如果键 key 不存在,则插入新的键值对。
- 如果键 key 已存在,则更新对应的值。
- mapName[key] = value;
- 查:
mapName.find(key)- 如果找到键 key,返回一个指向该键值对的迭代器。
- 如果未找到键 key,返回 mapName.end(),表示哈希表的末尾。
- 删:
mapName.erase(key);
- 遍历:
- 哈希表即键值对
给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:
- 子数组的长度是
k,且 - 子数组中的所有元素 各不相同 。
返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回0。
子数组 是数组中一段连续非空的元素序列。
class Solution {
public:
long long maximumSubarraySum(vector<int>& nums, int k) {
long long ans = 0,s = 0;
unordered_map<int, int> cnt;
for(int i = 0;i < nums.size();i++){
s += nums[i];
cnt[nums[i]]++;
int left = i - k + 1;
if(left < 0)continue;
if(cnt.size() == k)
ans = max(ans, s);
int out = nums[left];
s -= out;
if(--cnt[out] == 0)
cnt.erase(out);
}
return ans;
}
};
- 同上题题意相似, ≥m 改成 =k 即可。


浙公网安备 33010602011771号