【LeetCode】1052. 爱生气的书店老板 Grumpy Bookstore Owner(C++)


题目来源:https://leetcode-cn.com/problems/grumpy-bookstore-owner/

题目描述

今天,书店老板有一家店打算试营业 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 <= customers.length == grumpy.length <= 20000
0 <= customers[i] <= 1000
0 <= grumpy[i] <= 1

题目大意

  • 给定一个数组,当grumpy[i] = 0时,那一分钟的顾客是满意的,结果ans+=customers[i],求最多有多少客户能够感到满意的数量,让一定区间内的grumpy[i] = 0,然后结果ans加上那些customers[i]求个最值

前缀和

  • 先遍历一遍数组,先维护一个结果ans+=customers[i](前提是grumpy[i] == 0),顺便通过顾客数组,构造前缀和数组,可以O(1)时间复杂度完成区间[left,,right]之间的加和
  • 为了使前缀和数组sums[i]和顾客数组customers[i]统一
  • 前缀和数组sums和customers的关系,sums[i]为前i个customers的累加和(加到customers[i - 1])

s u m s [ k ] = { 0 ( k = = 0 ) ∑ i = 1 k c u s t o m e r s [ i − 1 ] ( k ∈ [ 1 , l e n ] ) sums[k] = \left\{ \begin{array}{c} 0 \quad\quad\quad\quad\quad\quad\quad\quad\qquad (k== 0) \\ \sum_{i=1}^{k}customers[i - 1] \quad\quad(k∈{[1, len]}) \\ \end{array}\right. sums[k]={ 0(k==0)i=1kcustomers[i1](k[1,len])

  • 区间[left,right](下标加1)的累加和(包含customers[left], customers[right]),注意处理边界问题

∑ s t a r t = l e f t r i g h t c u s t o m e r s [ s t r a t ] = s u m s [ r i g h t ] − s u m s [ l e f t − 1 ] \sum_{start = left}^{right}customers[strat] = sums[right] - sums[left-1]\quad\quad start=leftrightcustomers[strat]=sums[right]sums[left1]

  • 例如求数组中第一个数到第三个数之间所有元素值(包含区间边界customers[0]和customers[2])的累加和,sums[3]对应前3个,sums[0]对应前0个,所以相减即为所求

∑ s t a r t = 1 3 c u s t o m e r s [ s t r a t ] = s u m s [ 3 ] − s u m s [ 0 ] \sum_{start = 1}^{3}customers[strat] = sums[3] - sums[0]\quad\quad start=13customers[strat]=sums[3]sums[0]

const int MAXN = 2e4 + 1;
int sums[MAXN];
class Solution {
    
    
public:
    int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int winLen) {
    
    
        int ans = 0, len = customers.size();
        memset(sums, 0, sizeof(sums));
        for(int i = 1 ; i <= len ; ++i){
    
    
            if(grumpy[i - 1] == 0){
    
    
                ans += customers[i - 1];
                sums[i] = sums[i - 1];
            }
            else    sums[i] = sums[i - 1] + customers[i - 1];
        }
        int tempAns = ans;
        for(int i = 0; i < len ; ++i){
    
    
            // index = i + winLen
            if(i + winLen > len) break;
            int curSum = sums[i + winLen] - sums[i];
            ans = max(ans, tempAns + curSum);
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度:O(n)。n为数组的长度
  • 空间复杂度:O(n)。维护了一个前缀和数组,此处n取最大值2e4+1

可优化之处

  • 可将第一次循环处理过的某一分钟顾客满意的值设为0,即customers[i]=0(grumpy == 0),然后通过滑动窗口可将空间复杂度降为O(1)

猜你喜欢

转载自blog.csdn.net/lr_shadow/article/details/113988177