变长滑动窗口就先练这么多吧
2958. 最多 K 个重复元素的最长子数组
思路类似,代码简洁,先插入在判断,这里左指针移动的逻辑使用while会更加简洁一些。
cpp
class Solution {
public:
int maxSubarrayLength(vector<int>& nums, int k) {
int ans = 0;
unordered_map<int,int>umap;
int left = 0;
for(int right = 0;right < nums.size();right++){
int n = nums[right];
// 先插入右指针对应的元素
umap[n]++;
// 判断是否需要移动左指针
while(umap[n] > k){
umap[nums[left]]--;
left++;
}
ans = max(ans,right-left+1);
}
return ans;
}
};
2024. 考试的最大困扰度
和灵神的思路是一样的,但是我写的好累赘,,二进制次位有点不熟悉
cpp
class Solution {
public:
int maxConsecutiveAnswers(string answerKey, int k) {
int ans = 0;
// 大小为2,初始值为0
unordered_map<char,int>umap;
int temp = 0;
int left = 0;
umap['T'] = 0;
umap['F'] = 0;
for(int right = 0;right < answerKey.size();right++){
umap[answerKey[right]]++;
temp++;
while(min(umap['T'] , umap['F']) > k){
umap[answerKey[left]]--;
left++;
temp--;
}
ans = max(ans,temp);
}
return ans;
}
};
1004. 最大连续1的个数 III
和上一个题的思路一摸一样,就是注意存储数据的方式
cpp
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int ans = 0;
int left = 0;
int cnt = 0;
int flag[2] = {0};
for(int right = 0;right < nums.size();right++){
int n = nums[right];
flag[n]++;
cnt++;
while(flag[0] > k){
flag[nums[left]]--;
cnt--;
left++;
}
ans = max(ans,cnt);
}
return ans;
}
};
1658. 将 x 减到 0 的最小操作数
和之前有一个题非常的相似,也是求两侧的值,这种题都可以反着做,即变为滑动窗口问题(不定长双指针)
cpp
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
int ans = INT_MAX;
// 反着做,找最长的子数组
int sum = 0;
for(auto n:nums)
sum += n;
int max_long = 0;
int left = 0;
for(int right = 0;right < nums.size();right++){
max_long += nums[right];
while( (max_long > (sum - x)) && (left <= right)){
max_long -= nums[left];
left++;
}
if(max_long == (sum - x)) ans = min((int)nums.size() - (right - left + 1) , ans);
}
return (ans == INT_MAX)?-1:ans;
}
};
1208. 尽可能使字符串相等
原来这个题的两个字符串是对齐的,这就导致这个题就变成了正常的双指针的问题
cpp
class Solution {
public:
int equalSubstring(string s, string t, int maxCost) {
// 这个题貌似和我想得不一样
int ans = 0;
int cost = 0;
int left = 0;
for(int right = 0;right < s.size();right++){
cost += abs(s[right] - t[right]);
while(cost > maxCost){
cost -= abs(s[left] - t[left]);
left++;
}
ans = max(ans,right - left + 1);
}
return ans ;
}
};
2730. 找到最长的半重复子字符串
这个不需要用到哈希,要考虑好。写习惯了上来就想用哈希
cpp
class Solution {
public:
int longestSemiRepetitiveSubstring(string s) {
int ans = 0;
int left = 0;
int cnt = 0;
for(int right = 0;right < s.size();right++){
if((right > left) && s[right] == s[right-1]) cnt++;
while(cnt > 1){
if((right > left) && s[left] == s[left+1]) cnt--;
left++;
}
ans = max(ans,right-left+1);
}
return ans;
}
};