目录
有一个书店老板,他的书店开了 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 * 104
0 <= customers[i] <= 1000
grumpy[i] == 0 or 1
提示:以下是本篇文章正文内容,下面案例可供参考
一、题目分析
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
而滑动窗口则将只使用一个for循环
可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
二、代码实现
1.暴力实现
代码如下(示例):
class Solution {
public int maxSatisfied(int[] customers, int[] grumpy, int minutes) {
int temp=0,num=0;
for(int i=0;i<=customers.length-minutes;i++){
int sum=0;
for(int j=i;j<i+minutes;j++){
if(grumpy[j]==1)
sum+=customers[j];
}
if(sum>temp){
temp=sum;
num=i;
}
}
int sum2=0;
for(int i=0;i<customers.length;i++){
if(grumpy[i]==0){
sum2+=customers[i];
}
else if(i>=num&&i<num+minutes){
sum2+=customers[i];
}
}
return sum2;
}
}
2.滑动窗口
代码如下(示例):
class Solution {
public int maxSatisfied(int[] customers, int[] grumpy, int minutes) {
int sum=0;
for (int i = 0; i < customers.length; i++) {
if (grumpy[i] == 0) {
sum += customers[i];
customers[i] = 0;
}
}
int max=0,temp=0;
//滑动窗口探寻固定长度区间内的最大老板生气时的顾客流量
for(int left=0;left<customers.length;left++){
temp+=customers[left];
if(left>=minutes)temp-=customers[left-minutes];
max=Math.max(max,temp);
}
return sum+max;
}
}