【滑动窗口】LeetCode 1052. 爱生气的书店老板

2024-03-08 07:30

本文主要是介绍【滑动窗口】LeetCode 1052. 爱生气的书店老板,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1052. 爱生气的书店老板


题目来源:力扣(LeetCode)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

解题思路


思路:滑动窗口

先审题,题目给定的数组 c u s t o m e r s customers customers,其中:

  • 数组长度 l e n ( c u s t o m e r s ) len(customers) len(customers) 表示书店老板试营业的时间(单位:分钟);
  • 数组中的每个元素 c u s t o m e r s [ i ] customers[i] customers[i] 表示每分钟到店的顾客数。

其中,顾客从进店到离开的时间为一分钟,即是说,每分钟到店的顾客,一分钟结束后都会离开,而下一批顾客会进店。

现在题目中说明,书店的老板有个怪脾气,会在某些时候生气,只要老板生气,此时在店中的顾客就会不满意,否则顾客是满意的。

这里由数组 g r u m p y grumpy grumpy 表示老板当前时间是否是生气的状态,其中:

  • 元素值为 1 时,表示老板生气;
  • 元素值为 0 时,表示老板不生气。

而现在又知道,老板有个【秘密技巧】,能够抑制自己的情绪,让自己连续 X X X 分钟不会生气,但是只能使用一次。

最后,题目要求一天营业下来,最多能够使多少顾客满意?

根据上面的描述,可以分为两部分来看:

  • 正常情况下(即是不使用技巧),老板会生气,此时顾客会不满意,反之则满意;

  • 但老板能够使用【秘密技巧】,此时这段时间能够防止顾客不满意的情况出现,起到挽留的效果。

文中提及的 挽留,此篇题解均表使顾客满意。

因为明确知道使用【秘密技巧】,能够连续 X X X 分钟不生气,那么这里可以使用滑动窗口的技巧来解决本题,具体的思路如下:

  • 首先考虑正常情况下(不使用技巧)时,满意顾客的数量 t o t a l total total
  • 接着考虑老板使用 秘密技巧 时能够挽留的最大顾客数 m a x _ i n c r e a s e max\_increase max_increase,具体的方法:
    • 定义一个长度为 X X X 的窗口(表示使用技巧的这段时间),先计算窗口中能够挽留顾客的数量 i n c r e a s e increase increase
    • 移动窗口,此时窗口内会有元素离开及新元素被纳入。若离开元素为不满意的顾客,那么减少相应的顾客数,否则不处理。若纳入的新元素为不满意的顾客,这部分会被挽留,那么需要增加相应的顾客数。
  • 最终,窗口移动到末尾时, t o t a l total total m a x _ i n c r e a s e max\_increase max_increase 的和即是最多能使顾客满意的数量。

以题目示例,用图示的方式展示下效果,如下:

动图

具体的代码实现如下。

class Solution:def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int:total = 0n = len(customers)# n = len(grumpy)# 先考虑老板不使用秘密技巧的情况for i in range(n):if grumpy[i] == 0:total += customers[i]# 使用滑动窗口的技巧# 窗口从数组头部开始,先计算当前窗口能挽留的顾客数increase = 0for i in range(X):# 窗口表示老板使用秘密技巧的一段时间# 此时,老板不会生气,那么原本因老板生气的顾客将不会不满意if grumpy[i] == 1:increase += customers[i]# 记录窗口移动,能挽留的最大顾客数max_increase = increase# 窗口进行移动for i in range(X, n):# 若离开窗口的是不满意的顾客,那么原本挽留的顾客数将相应减少if grumpy[i - X] == 1:increase -= customers[i - X]# 若进入窗口的是不满意的顾客,那么挽留的顾客相应增加if grumpy[i] == 1:increase += customers[i]max_increase = max(increase, max_increase)return total + max_increase

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n) n n n 为数组 c u s t o m e r s customers customers g r u m p y grumpy grumpy 的长度。
  • 空间复杂度: O ( 1 ) O(1) O(1)

欢迎关注


公众号 【书所集录】


如有错误,烦请指出,欢迎指点交流。若觉得写得还不错,麻烦点个赞👍,谢谢。

这篇关于【滑动窗口】LeetCode 1052. 爱生气的书店老板的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/786431

相关文章

bat脚本启动git bash窗口,并执行命令方式

《bat脚本启动gitbash窗口,并执行命令方式》本文介绍了如何在Windows服务器上使用cmd启动jar包时出现乱码的问题,并提供了解决方法——使用GitBash窗口启动并设置编码,通过编写s... 目录一、简介二、使用说明2.1 start.BAT脚本2.2 参数说明2.3 效果总结一、简介某些情

基于Redis有序集合实现滑动窗口限流的步骤

《基于Redis有序集合实现滑动窗口限流的步骤》滑动窗口算法是一种基于时间窗口的限流算法,通过动态地滑动窗口,可以动态调整限流的速率,Redis有序集合可以用来实现滑动窗口限流,本文介绍基于Redis... 滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 + 哈希表这里用哈希集合Set()实现。左指针i,右指针j,从头遍历数组,若j指针指向的元素不在set中,则加入该元素,否则更新结果res,删除集合中i指针指向的元素,进入下一轮循环。 /*** @param