思路:维护一个长度为k的滑动窗口,并用一个使用一个unorder_map映射记录在该窗中中‘W’和'B'的个数。那么,要保证有一个长度为k的全为‘B’的字符串,就只需要把对应map中,键‘W’全改为‘B’即可。也就是说对于当前窗口,要实现全为‘B’的字符串,需要操作的次数就是键‘W’对应的值。基于这个思想,让窗口依次向下滑动即可。
#include<iostream>
#include<vector>
#include<cstdlib>
#include<unordered_map>
using namespace std;
class Solution {
public:
int minimumRecolors(string blocks, int k) {
unordered_map<char,int> mp;
int size = blocks.size();
// 记录第一个窗口的对应映射
for(int i=0;i<k;i++){
mp[blocks[i]]++;
}
int tempOp=mp['W'],minOp = mp['W'];
for(int i=1;i<size-k+1;i++){
mp[blocks[i-1]]--;
mp[blocks[i+k-1]]++;
tempOp=mp['W'];
minOp = min(minOp,tempOp);
}
return minOp;
}
};
思路:本题困于如何实现循环数组,使用了取模的方式。但是官方题解给出了一种更好的方式来求解,即将原来的code数组,扩容成原来的两倍,并且将code数组原来的数据直接赋值给后面一半,这样当访问数组第i+k个元素时,就不存在越界问题了。之后的操作就是普通的滑动窗口了。
class Solution {
public:
vector<int> decrypt(vector<int>& code, int k) {
int n = code.size();
vector<int> res(n);
if (k == 0) {
return res;
}
code.resize(n * 2);
copy(code.begin(), code.begin() + n, code.begin() + n);
int l = k > 0 ? 1 : n + k;
int r = k > 0 ? k : n - 1;
int w = 0;
for (int i = l; i <= r; i++) {
w += code[i];
}
for (int i = 0; i < n; i++) {
res[i] = w;
w -= code[l];
w += code[r + 1];
l++;
r++;
}
return res;
}
};
思路:先计算出所有时间下不生气的人数总和,再利用滑动窗口不断向后滑动,处理再当前窗口内老板生气的情况下忍住的所有不生气人数。
#include <iostream>
#include <vector>
#include <cstdlib>
#include <map>
using namespace std;
class Solution {
public:
int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
int totalSatisfied = 0;
int maxAdditionalSatisfied = 0;
int currentAdditionalSatisfied = 0;
int size = customers.size();
// 计算在不生气的情况下的总满意顾客数
for (int i = 0; i < size; i++) {
if (grumpy[i] == 0) {
totalSatisfied += customers[i];
}
}
// 计算前 'minutes' 分钟内的额外满意顾客数
for (int i = 0; i < minutes; i++) {
if (grumpy[i] == 1) {
currentAdditionalSatisfied += customers[i];
}
}
maxAdditionalSatisfied = currentAdditionalSatisfied;
// 使用滑动窗口计算其他时间段的额外满意顾客数
for (int i = minutes; i < size; i++) {
if (grumpy[i] == 1) {
currentAdditionalSatisfied += customers[i]; // 新加入的
}
if (grumpy[i - minutes] == 1) {
currentAdditionalSatisfied -= customers[i - minutes]; // 移除的
}
maxAdditionalSatisfied = max(maxAdditionalSatisfied, currentAdditionalSatisfied);
}
return totalSatisfied + maxAdditionalSatisfied; // 返回总满意顾客数
}
};
思路:基本上就是简单的滑动窗口,只是要记录一个map映射,用来保存当前窗口内有多少对不同的map映射,用来和m进行比较,只有当map映射数满足大于等于m时,采取尝试更新最终的maxSum。这道题两个注意点(我自己的错误),第一,map映射的值在为0时,并不会主动删去,所以要手动使用erase方法;第二,对于求和变量curSum和maxSum最好要开long long。
#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
long long maxSum(vector<int>& nums, int m, int k) {
unordered_map<int,int> mp;
int size = nums.size();
if(m>size) return 0;
long long curSum=0,maxSum=0;
for(int i=0;i<k;i++){
mp[nums[i]]++;
curSum+= nums[i];
}
if(mp.size()>=m) maxSum=curSum;
for(int i=1;i<size-k+1;i++){
mp[nums[i-1]]--;
if(mp[nums[i-1]]==0) mp.erase(nums[i-1]);
mp[nums[i-1+k]]++;
curSum = curSum-nums[i-1]+nums[i-1+k];
if(mp.size()>=m) maxSum = max(maxSum,curSum);
}
return maxSum;
}
};
思路:与上一题几乎完全一致,只是一个是小于m,一个是等于k,不赘述。
class Solution {
public:
long long maximumSubarraySum(vector<int>& nums, int k) {
unordered_map<int,int> mp;
int size = nums.size();
if(k>size) return 0;
long long curSum=0,maxSum=0;
for(int i=0;i<k;i++){
mp[nums[i]]++;
curSum += nums[i];
}
if(mp.size()==k) maxSum=curSum;
for(int i=1;i<size-k+1;i++){
mp[nums[i-1]]--;
if(mp[nums[i-1]]==0) mp.erase(nums[i-1]);
mp[nums[i-1+k]]++;
curSum = curSum-nums[i-1]+nums[i-1+k];
if(mp.size()==k) maxSum = max(maxSum,curSum);
}
return maxSum;
}
};