本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、题目描述:
1052. 爱生气的书店老板 - 力扣(LeetCode) (leetcode-cn.com)
有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。给定一个长度为 n 的整数数组 customers ,其中 customers[i] 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟结束后离开。
在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1,否则 grumpy[i] = 0。
当书店老板生气时,那一分钟的顾客就会不满意,若老板不生气则顾客是满意的。
书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 minutes 分钟不生气,但却只能使用一次。
请你返回 这一天营业下来,最多有多少客户能够感到满意 。
示例 1:
输入:customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], minutes = 3
输出:16
解释:书店老板在最后 3 分钟保持冷静。
感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.
示例 2:
输入:customers = [1], grumpy = [0], minutes = 1
输出:1
提示:
- n == customers.length == grumpy.length
- 1 <= minutes <= n <= 2 * 10^4
- 0 <= customers[i] <= 1000
- grumpy[i] == 0 or 1
二、思路分析:
- 计算老板不生气时的顾客数总和total
- 维护一个长度为X滑动窗口,该窗口代表老板的冷静期,结果需要算上该冷静期内的所有顾客数
- 当窗口扩大时,计算窗口内是否有老板生气的元素,即grumpy[i]值为1,有的话假设老板在该窗口冷静,则total加上当前i索引对应的顾客数;
- 当窗口缩小时,即窗口超过X个元素进行窗口缩小,如果从窗口移出的元素grumpy[i]的值为1,说明刚才total已经加上了该i索引的顾客数,所以此时需要减掉i索引对应的顾客数
- 窗口每次移动时,取total的最大值即可
三、AC 代码:
/**
* @param {number[]} customers
* @param {number[]} grumpy
* @param {number} X
* @return {number}
*/
var maxSatisfied = function(customers, grumpy, X) {
// 不生气时所有的顾客满意数
let total = 0;
for (let i = 0; i < customers.length; i++) {
if (grumpy[i] === 0) {
total += customers[i];
}
}
let result = total;
let left = 0;
let right = 0;
// 双指针维护长度为X的一个窗口
while (right < customers.length) {
// 新加入窗口的元素看是否是生气的,是的话加上该顾客人数
if (grumpy[right]) {
total += customers[right];
}
// 缩小窗口,缩小的元素是生气的,那减去该顾客的人数
if (right - left == X) {
if (grumpy[left]) {
total -= customers[left];
}
left++;
}
right++;
// 取最大值
result = Math.max(result, total);
}
return result;
};