爱生气的书店老板
题目描述
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 <= customers.length == grumpy.length <= 20000
0 <= customers[i] <= 1000
0 <= grumpy[i] <= 1
题解代码
暴力解法
1 class Solution { 2 public int maxSatisfied(int[] customers, int[] grumpy, int X) { 3 int maxSatisfied = 0; 4 for(int i = 0;i<=customers.length-X;i++){ 5 int curSatisfied=0; 6 for(int j = 0;j<i;j++){//连续不生气之前 7 curSatisfied+=customers[j]*(1-grumpy[j]); 8 } 9 for(int j=i;j<=i+X-1;j++){//连续不生气 10 curSatisfied+=customers[j]; 11 } 12 for(int j=i+X;j<customers.length;j++){//连续不生气之后 13 curSatisfied+=customers[j]*(1-grumpy[j]); 14 } 15 maxSatisfied=Math.max(maxSatisfied,curSatisfied); 16 } 17 return maxSatisfied; 18 } 19 }
暴力解法思路很简单,只是在grumpy数组上滑窗长度为X的区间,作为连续不生气的时间区间。
观察发现暴力解法每次都统计整个数组的和,但其实对于没有使用技巧的和,使用技巧后的和只是改变了长度为X的滑动窗口的部分和,因此可以先求出整个数组的和,再计算滑动窗口内翻转的部分和的最大值,于是就有了下面的优化解法。
优化解法
1 class Solution { 2 public int maxSatisfied(int[] customers, int[] grumpy, int X) { 3 int allSatisNum = 0; 4 for(int i=0;i<customers.length;i++){ 5 allSatisNum += customers[i]*(grumpy[i]^1);//统计没有使用秘密技巧时满意的人数总和 6 } 7 int curExtraNum = 0; 8 int maxExtraNum = 0; 9 for(int i=0;i<X;i++){//计算首个滑动窗口的翻转部分和 10 curExtraNum += customers[i]*grumpy[i]; 11 } 12 maxExtraNum = curExtraNum; 13 for(int i=X;i<customers.length;i++){//滑动窗口 14 curExtraNum += customers[i]*grumpy[i];//加上滑动窗口右移新添的 15 curExtraNum -= customers[i-X]*grumpy[i-X];//减去滑动窗口右移抛弃的 16 maxExtraNum = Math.max(curExtraNum,maxExtraNum);//更新翻转部分和的最大值 17 } 18 return allSatisNum + maxExtraNum; 19 } 20 }
进一步优化
仔细观察发现,上述解法对customers数组进行了两次互不干扰的遍历,因此,两次遍历可以合为一次。
1 class Solution { 2 public int maxSatisfied(int[] customers, int[] grumpy, int X) { 3 int allSatisNum = 0; 4 int curExtraNum = 0; 5 int maxExtraNum = 0; 6 for(int i=0;i<customers.length;i++){ 7 allSatisNum += customers[i]*(grumpy[i]^1);//统计没有使用秘密技巧时满意的人数总和 8 if(i<X){//计算首个滑动窗口的翻转部分和 9 curExtraNum += customers[i]*grumpy[i]; 10 maxExtraNum = curExtraNum; 11 }else{ 12 curExtraNum += customers[i]*grumpy[i];//加上滑动窗口右移新添的 13 curExtraNum -= customers[i-X]*grumpy[i-X];//减去滑动窗口右移抛弃的 14 if(curExtraNum>maxExtraNum){ 15 maxExtraNum = curExtraNum;//更新翻转部分和的最大值 16 } 17 } 18 } 19 return allSatisNum + maxExtraNum; 20 } 21 }

浙公网安备 33010602011771号