【滑动窗口】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

相关文章

哈希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

LeetCode:64. 最大正方形 动态规划 时间复杂度O(nm)

64. 最大正方形 题目链接 题目描述 给定一个由 0 和 1 组成的二维矩阵,找出只包含 1 的最大正方形,并返回其面积。 示例1: 输入: 1 0 1 0 01 0 1 1 11 1 1 1 11 0 0 1 0输出: 4 示例2: 输入: 0 1 1 0 01 1 1 1 11 1 1 1 11 1 1 1 1输出: 9 解题思路 这道题的思路是使用动态规划

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析