1004. 最大连续1的个数 III
给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。
返回仅包含 1 的最长(连续)子数组的长度。
示例 1:
输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:
[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
题解:
基本上来说,M级别或以下的滑窗题只要翻译对了题目是比较容易的。总结了要点有以下两点:
1.争取把题目翻译成“找出XXX样的最长连续子串”。
2.找最长的时候,记得最后只需要保证left和right被撑到最大,然后一直移动到末端就可以了。而不用具体的找出是哪段数据最长。
如本题:
[最多可以把 K 个 0 变成 1,求仅包含 1 的最长子数组的长度]转换为 [找出一个最长的子数组,该子数组内最多允许有 K 个 0 ]。
//找出变换K个最长的1,即找出最多包含K个0的最长子列
class Solution {
public:
int longestOnes(vector<int>& A, int K) {
int left = 0;
int zero = 0;
int i = 0;
for (; i < A.size(); i++)
{
if (A[i] == 0)
zero++;
if (zero > K)
{
if (A[left] == 0)
zero--;
left++; //如果0数量超标,左指针才会移动
}
}
return i - left;
}
};
1438. 绝对差不超过限制的最长连续子数组
给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。
如果不存在满足条件的子数组,则返回 0 。
示例:
输入:nums = [10,1,2,4,7,2], limit = 5
输出:4
解释:满足题意的最长子数组是 [2,4,7,2],其最大绝对差 |2-7| = 5 <= 5 。
题解:
本题核心,维护窗口内最大值和最小值。我用的map,官方题解用的multiset,其实差不多。要注意multiset也是自动排序的,默认小到大,与set的区别就是可以允许有重复元素出现。
此外,用rbegin()表示最后一个元素。这个意思是,反向遍历的头元素。
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
map<int,int> mp; //利用按键值大小排序
int left = 0;
int i = 0;
for (; i < nums.size(); i++)
{
if (mp.count(nums[i]))//出现过
mp[nums[i]]++;
else
mp.insert({ nums[i],1 });
int minn = mp.begin()->first;
int maxn = mp.rbegin()->first;
if (abs(maxn - minn) > limit)
{
//踢出一个left更新map
if (mp[nums[left]] == 1)
mp.erase(nums[left]);
else
mp[nums[left]]--;
left++; //左指针右移
}
}
return i - left;
}
};
1052. 爱生气的书店老板
今天,书店老板有一家店打算试营业 customers.length 分钟。每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开。
在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1,否则 grumpy[i] = 0。 当书店老板生气时,那一分钟的顾客就会不满意,不生气则他们是满意的。
书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 X 分钟不生气,但却只能使用一次。
请你返回这一天营业下来,最多有多少客户能够感到满意的数量。
示例:
输入:customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], X = 3
输出:16
解释:
书店老板在最后 3 分钟保持冷静。
感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.
题解:简单题,只要读懂题意很好理解。维护一个大小为K的窗口,依次看这个窗口比之前的情况增加了多少,然后选择这些窗口中增加最大的情况。因为除了窗口之外的和是固定的,增加的越多,处理后的和也就越大。
class Solution {
public:
int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int X) {
int n = customers.size();
//异或处理,方便后面直接用乘法
for (int i = 0; i < n; i++)
grumpy[i] = grumpy[i] ^ 1;
int more = 0, sum = 0;
for (int i = 0; i < X; i++) //初始化第一个窗口
{
more += customers[i] - (customers[i] * grumpy[i]);
sum += (customers[i] * grumpy[i]); //顺便统计原始和
}
int maxmore = more;
for (int i = X; i < n; i++)
{
int left = i - X;
more -= customers[left] - (customers[left] * grumpy[left]); //踢掉左边指针
more += customers[i] - (customers[i] * grumpy[i]);//加入右边指针
maxmore = max(maxmore, more);
sum += (customers[i] * grumpy[i]);//顺便统计原始和
}
return sum + maxmore;
}
};