1052. 爱生气的书店老板(中等题)--滑动窗口

力扣--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.

提示:

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 1Xcustomers.length=grumpy.length20000
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 0customers[i]10000grumpy[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;
    }
};

这次提交就通过了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗小芋圆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值