2379. 得到 K 个黑块的最少涂色次数
cpp
class Solution {
public:
int minimumRecolors(string blocks, int k) {
int ans = INT_MAX;
int temp = 0;
for(int right = 0;right < blocks.size();right++){
if(blocks[right] == 'W') temp++;
int left = right - k + 1;
if(left < 0) continue;
ans = min(ans,temp);
if(blocks[left] == 'W') temp--;
}
return ans;
}
};
2841. 几乎唯一子数组的最大和
这里查重使用的是umap而不是uset,主要原因是因为uset在进行清除元素不容易,如果采用在循环中构建uset来查重的话时间复杂度会超。
使用umap时,注意键值对应该是《元素值,元素值出现的次数》
当元素对应的次数为0时,要进行erase擦除元素
cpp
class Solution {
public:
long long maxSum(vector<int>& nums, int m, int k) {
long long ans = 0;
long long temp = 0;
unordered_map<int,long>umap;
for(int right = 0;right < nums.size();right++){
temp += nums[right];
umap[nums[right]]++;
// 判断
int left = right - k + 1;
if(left < 0) continue;
// 查重
// 这里不能用set,还是会超时
// unordered_set<int>uset(nums.begin()+left,nums.begin()+right+1);
if(umap.size() >= m) ans = max(ans,temp);
// 如果符合要求,将记录答案
// 不符合要求则不需要操作
temp -= nums[left];
umap[nums[left]]--;
if(umap[nums[left]] == 0)
umap.erase(nums[left]);
}
return ans;
}
};
2461. 长度为 K 子数组中的最大和
和上一个题的思路一模一样
cpp
class Solution {
public:
long long maximumSubarraySum(vector<int>& nums, int k) {
long long ans = 0;
long long temp = 0;
unordered_map<int,int>umap;
int left = 0;
for(int right = 0;right < nums.size();right++){
int in = nums[right];
temp += in;
umap[in]++;
left = right - k + 1;
if(left < 0) continue;
if(umap.size() == k) ans = max(ans,temp);
int out = nums[left];
temp -= out;
if(!(--umap[out])) umap.erase(out);
}
return ans;
}
};
1423. 可获得的最大点数
这个题想半天没什么好的思路,但是暴力遍历是可以通过的(我以为会超时)
cpp
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int ans = 0, sum = 0;
for(int left = 0;left < k ;left++){
sum += cardPoints[left];
int temp = 0;
for(int right = cardPoints.size() - 1;(cardPoints.size() - right) <= (k - left - 1) ;right--){
temp += cardPoints[right];
}
ans = max(ans,sum + temp);
}
sum = 0;
for(int begin = cardPoints.size() - 1;k > 0 ;k--,begin--){
sum+=cardPoints[begin];
}
return max(ans,sum);
}
};
想到的优化就是去维护一个数组,和之前的想法一样,进一个出一个。只不过这次是先出在近判断。因此在对右侧累加结束后赋值给ans,从而把全选择右侧的情况包含进去。
查看题解发现大家有好多新的思路:
反向思考:找两侧的最大和不就是找中间的最小和嘛,或者把左右两侧链接起来变为一个环形数组也是可以的(感觉这个实现会有一些困难)
cpp
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int sum = 0;
// 单独求一下rsum
for(int i = cardPoints.size() - 1;i >= (int)(cardPoints.size() - k);i--){
sum += cardPoints[i];
}
int ans = sum;
for(int left = 0;left < k ;left++){
sum += cardPoints[left];
sum -= cardPoints[cardPoints.size() - k + left];
ans = max(ans,sum);
}
return ans;
}
};
3679. 使库存平衡的最少丢弃次数!!!!!!【重点】
把易错点写在解析了。这个太难注意了
cpp
class Solution {
public:
int minArrivalsToDiscard(vector<int>& arrivals, int w, int m) {
int ans = 0;
unordered_map<int,int>umap;
for(int right = 0;right < arrivals.size();right++){
int &in = arrivals[right];
umap[in]++;
if(umap[in] > m){
umap[in]--;
ans++;
// 这里要把对应的值也要修改
// 不然元素出来还会重复计算,没起到丢弃的效果!!!
in = -1;
}
int left = right - w + 1;
if(left < 0) continue;
int out = arrivals[left];
if((--umap[out])==0) umap.erase(out);
}
return ans;
}
};