思路:利用滑动窗口
如果老板没有“灵丹妙药”,则在给定 customers 和 grumpy 数组的前提下满意的顾客总数量是唯一确定的;但有了此“药”后,老板便能在指定的 minutes 时间间隔内保持心态平和,从而可能使满意顾客总数量的增加;又因为 minutes 长度的时间间隔从哪个时刻(第几分钟)开始不确定,因而就存在满意顾客数量的最大值。因而:
- 先计算出没有“灵丹妙药”情况下满意顾客的总数量,赋值给 res;
- 利用 grumpy 的值( 0 或 1 )更新 customers 的值,即令 customers 只显示第 i 分钟不满意的顾客量,以便将原问题转化为求解 minutes 大小的 customers 的连续子序列和的最大值 maxx
- 如果 grumpy[i] = 0 (老板慈祥中,已包含进 res),置 customers[i] = 0;
- 反之,customers[i] 的值不变;
- 遍历 customers 数组得 maxx,返回原先满意的顾客总量 res + 老板药后新增的顾客量 maxx。
Input : customers = [ 1,0,1,2,1,1,7,5 ],grumpy = [ 0,1,0,1,0,1,0,1 ],minutes = 3
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
customers[i] | 1 | 0 | 1 | 2 | 1 | 1 | 7 | 5 |
grumpy[i] | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
customers[i] * grumpy[i] | 0 | 0 | 0 | 2 | 0 | 1 | 0 | 5 |
上述测试用例 res = 1 + 1 + 1 + 7 = 10
所有滑动窗口对应 customers 的值集为 {0, 0, 0}, {0, 0, 2}, {0, 2, 0}, {2, 0, 1}, {0, 1, 0}, {1, 0, 5}, 故 maxx = 1 + 0 + 5 = 6
class Solution {
public:
int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
int n = customers.size(), res = 0, maxx = 0;
for(int i = 0; i < n; i++) {
if(grumpy[i] == 0) res += customers[i];
customers[i] *= grumpy[i];
}
for(int i = 0; i <= n - minutes; i++) {
int sum = accumulate(customers.begin() + i, customers.begin() + i + minutes, 0);
if(sum > maxx) maxx = sum;
}
return res + maxx;
}
};
稍作优化:
使用变量 temp 存储长度为 minutes 的连续子序列的和。
参考https://leetcode.com/problems/grumpy-bookstore-owner/discuss/299237/C%2B%2B-Sliding-Window
class Solution {
public:
int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
int n = customers.size(), res = 0, maxx = 0, temp = 0;
for (int i = 0; i < n; i++) {
if (grumpy[i] == 0)
res += customers[i];
temp += grumpy[i] * customers[i];
if (i >= minutes)
temp -= grumpy[i - minutes] * customers[i - minutes];
maxx = max(temp, maxx);
}
return res + maxx;
}
};