这题最开始写的超时了,后来发现之前的写法有很多重复的计算,优化之后就过了,感觉这种写法遇到蛮多次的,做个笔记。
原题传送门
【题目描述】
今天,书店老板有一家店打算试营业 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.
提示:
1 ≤ X ≤ c u s t o m e r s . l e n g t h = g r u m p y . l e n g t h ≤ 20000 1 \le X \le customers.length = grumpy.length \le 20000 1≤X≤customers.length=grumpy.length≤20000
0 ≤ c u s t o m e r s [ i ] ≤ 10000 ≤ g r u m p y [ i ] ≤ 1 0 \le customers[i] \le 1000 0 \le grumpy[i] \le 1 0≤customers[i]≤10000≤grumpy[i]≤1
【直接暴力】
【思路】
直接遍历列表,先统计出老板不生气时的顾客数,这是基础值,无论是否控制情绪,都会有这么多顾客满意。接下来,就是找到可以通过控制情绪,使不满意变成满意的顾客的最大数量。这些数值必须是连续X天,基于以上分析,就有了下面这个代码:
【代码】
class Solution {
public:
int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int X) {
int ans=0;
int temp=0;int plus=0;
int n=customers.size();
for(int i=0;i<n;i++){
temp=0;
if(grumpy[i]==0){//累加基础值
ans+=customers[i];
}
for(int j=i;j<(i+X);j++){//每次都找接下来X天内,可以争取的数量
if(grumpy[j]==1){
temp+=customers[j];
}
if(j==n-1){
break;
}
}
if(temp>plus){//更新最大值
plus=temp;
}
}
ans=ans+plus;//基础值+可争取的最大值
return ans;
}
};
上面的代码交上去,在第77个测试点超时。经过分析,发现每次找接下来的X天时会重复计算,可以想象有一个长度为X的窗口,每次滑动一格,每次改变,只会改变左边界和右边界两个值,所以做了优化:
【滑动窗口代码】
class Solution {
public:
int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int X) {
int ans=0;
int temp=0;int plus=0;
int n=customers.size();
for(int j=0;j<X;j++){//生气的,找到可以增加的最大值
if(grumpy[j]==1){
temp+=customers[j];
}
if(j>=n-1){
break;
}
}
for(int i=0;i<n;i++){
if(grumpy[i]==0){//不生气的,这是基础值
ans+=customers[i];
}
if(i>0){
if(grumpy[i-1]==1){//窗口移动,删除左边界值
temp-=customers[i-1];
}
if((i+X-1)<n){
if(grumpy[i+X-1]==1){//增加右边界值
temp+=customers[i+X-1];
}
}
}
if(temp>plus){//更新最大值
plus=temp;
}
}
ans=ans+plus;
return ans;
}
};
这次提交就通过了。