算法刷题打卡第90天:表现良好的最长时间段

news2024/11/28 8:47:07

表现良好的最长时间段

难度:中等

给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。

我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。

所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。

请你返回「表现良好时间段」的最大长度。

示例 1:

输入:hours = [9,9,6,0,6,6,9]
输出:3
解释:最长的表现良好时间段是 [9,9,6]。

示例 2:

输入:hours = [6,6,6]
输出:0

前置知识:前缀和

对于数组 nums \textit{nums} nums,定义它的前缀和 s [ 0 ] = 0 \textit{s}[0]=0 s[0]=0 s [ i + 1 ] = ∑ j = 0 i nums [ j ] 。 \textit{s}[i+1] = \sum\limits_{j=0}^{i}\textit{nums}[j]。 s[i+1]=j=0inums[j]
例如 nums = [ 1 , 2 , − 1 , 2 ] \textit{nums}=[1,2,-1,2] nums=[1,2,1,2],对应的前缀和数组为 s = [ 0 , 1 , 3 , 2 , 4 ] s=[0,1,3,2,4] s=[0,1,3,2,4]

通过前缀和,我们可以把子数组的元素和转换成两个前缀和的差,即

∑ j = left right nums [ j ] = ∑ j = 0 right nums [ j ] − ∑ j = 0 left − 1 nums [ j ] = s [ right + 1 ] − s [ left ] \sum_{j=\textit{left}}^{\textit{right}}\textit{nums}[j] = \sum\limits_{j=0}^{\textit{right}}\textit{nums}[j] - \sum\limits_{j=0}^{\textit{left}-1}\textit{nums}[j] = \textit{s}[\textit{right}+1] - \textit{s}[\textit{left}] j=leftrightnums[j]=j=0rightnums[j]j=0left1nums[j]=s[right+1]s[left]
例如 nums \textit{nums} nums的子数组 [ 2 , − 1 , 2 ] [2,-1,2] [2,1,2] 的和就可以用 s [ 4 ] − s [ 1 ] = 4 − 1 = 3 s[4]-s[1]=4-1=3 s[4]s[1]=41=3 算出来。

注:为方便计算,常用左闭右开区间 [ left , right ) [\textit{left},\textit{right}) [left,right) 来表示子数组,此时子数组的和为 s [ right ] − s [ left ] \textit{s}[\textit{right}] - \textit{s}[\textit{left}] s[right]s[left],子数组的长度为 right − left \textit{right}-\textit{left} rightleft

方法一:单调栈

思路:

先把问题转换到我们熟悉的东西上。

「劳累天数大于不劳累天数」等价于「劳累天数减去不劳累天数大于 0 0 0」。

那么把劳累的一天视作 nums [ i ] = 1 \textit{nums}[i]=1 nums[i]=1,不劳累的一天视作 nums [ i ] = − 1 \textit{nums}[i]=-1 nums[i]=1,则问题变为:

计算 nums \textit{nums} nums 的最长子数组,其元素和大于 0 0 0

既然说到了「子数组的元素和」,那么利用前缀和 s s s,将问题变为:

找到两个下标 i i i j j j,满足 j < i j<i j<i s [ j ] < s [ i ] s[j]<s[i] s[j]<s[i],最大化 i − j i-j ij 的值。

想一想,哪些值可以作为 j j j(最长子数组的左端点)呢?

在这里插入图片描述
复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n hours \textit{hours} hours的长度。注意每个元素至多入栈出栈各一次,因此二重循环的时间复杂度是 O ( n ) O(n) O(n) 的。
  • 空间复杂度: O ( n ) O(n) O(n)
class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        hours_sum, start = [0] * (len(hours) + 1), [0]
        for i in range(len(hours)):
            # 前缀和
            hours_sum[i+1] = hours_sum[i] + 1 if hours[i] > 8 else hours_sum[i] - 1
            # 可能是开头的位置
            if hours_sum[start[-1]] > hours_sum[i+1]:
                start.append(i+1)
        res = 0
        for i in range(len(hours), 0, -1):
            while start and hours_sum[i] > hours_sum[start[-1]]:
                res = max(res, i - start.pop())
        return res

方法二:利用前缀和的连续性

虽说方法一更加通用,不过利用 nums \textit{nums} nums中只有 1 1 1 − 1 −1 1 的特点,可以做到一次遍历。

考虑 s [ i ] s[i] s[i]

  • 如果 s [ i ] > 0 s[i]>0 s[i]>0,那么 j = 0 j=0 j=0 就是最远的左端点,因为 s [ 0 ] = 0 s[0]=0 s[0]=0,故 s [ i ] − s [ 0 ] = s [ i ] > 0 s[i]-s[0]=s[i]>0 s[i]s[0]=s[i]>0,符合要求。
  • 如果 s [ i ] ≤ 0 s[i]\le 0 s[i]0,那么 jjj 就是 s [ i ] − 1 s[i]-1 s[i]1 首次出现的位置。为什么是 s [ i ] − 1 s[i]-1 s[i]1 而不是其它更小的数?这是因为前缀和是从 0 0 0 开始的,由于 nums \textit{nums} nums 中只有 1 1 1 − 1 −1 1,那么相邻前缀和的差都恰好为 1 1 1,要想算出比 s [ i ] − 1 s[i]-1 s[i]1 更小的数,必然会先算出 s [ i ] − 1 s[i]-1 s[i]1,那么这些更小数必然在 s [ i ] − 1 s[i]-1 s[i]1 首次出现的位置的右边。
    请添加图片描述

代码实现时,可以用哈希表记录每个 s [ i ] s[i] s[i] 首次出现的下标。

不过,由于我们只需要考虑值在闭区间 [ − n , 0 ] [-n,0] [n,0] 内的前缀和,用数组记录是更加高效的。同时,为了避免用负数访问数组,可以在计算过程中把前缀和取反。

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n hours \textit{hours} hours的长度。
  • 空间复杂度: O ( n ) O(n) O(n)
class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        pos = [0] * (len(hours) + 2) # 记录前缀和首次出现的位置
        res = sums = 0
        for i, j in enumerate(hours, 1):
            sums += -1 if j > 8 else 1 # 取反,改为减法
            if sums < 0:
                res = i
            else:
                if pos[sums+1]: # 原本是 sums-1,取反改为 sums+1
                    res = max(res, i-pos[sums+1]) # 这里手写 if 会更快
                if pos[sums] == 0:
                    pos[sums] = i
        return res

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-well-performing-interval/solutions/2110211/liang-chong-zuo-fa-liang-zhang-tu-miao-d-hysl/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/345149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常量const、引用、指针的大杂烩

文章目录1 普通引用1.1 对普通值的普通引用1.2 对常量值的普通引用1.3 对普通指针的普通引用1.4 对常量指针的普通引用1.5 对指针常量的普通引用1.6 对指向常量的指针常量的普通引用2 常量引用2.1 对普通值的常量引用2.2 对常量值的常量引用2.3 对普通指针的常量引用2.4 对常量…

2023年留学基金委(CSC)西部/地方合作项目选派办法及解读

2023年2月13日国家留学基金委&#xff08;CSC&#xff09;官方网站发布了2023年西部地区人才培养特别项目、地方合作项目通知。知识人网小编现将其选派工作流程及选派办法原文转载并加以解读、提出建议。知识人网建议1. 邀请函是公派申请的必备条件。对于外语语言证明未达标者&…

React学习笔记(番外二)——列表多选批量处理复合组件

React学习笔记&#xff08;番外二&#xff09;——列表多选批量操作复合组件前言〇、Show you the code一、 任务分析及拆解表头行的Checkbox——总开关记录行的Checkbox——行级开关二、 基础实现表头行的文件——header-row.js记录行的文件——record-row.js页面的文件App.js…

Linux操作系统学习(进程退出)

文章目录进程终止退出码进程退出场景进程退出的方式进程终止 退出码 ​ 我们知道每个main函数结尾都有return&#xff0c;一般都是return 0&#xff0c;用echo $&#xff1f;就可以查看它的退出码&#xff0c;0就是他的退出码&#xff0c;也可以写一些别的数值&#xff0c;比…

微服务项目【网关服务限流熔断降级分布式事务】

网关服务限流熔断降级 第1步&#xff1a;启动sentinel-dashboard控制台和Nacos注册中心服务 第2步&#xff1a;在网关服务中引入sentinel依赖 <!-- sentinel --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-…

好好学react源码然后惊艳所有人

hello&#xff0c;这里是潇晨&#xff0c;今天我们来聊聊react源码&#xff0c;作为使用react多年的前端工程师&#xff0c;我们是否还在使用着各种应用层面的库、框架呢&#xff0c;是否在面试过程中遇到一些关于react源码方面的问题呢&#xff0c;如果是&#xff0c;那么是否…

数据结构与算法:java对象的比较

1.基本类型的比较 在Java中&#xff0c;基本类型的对象可以直接比较大小。 public class TestCompare {public static void main(String[] args) {int a 10;int b 20;System.out.println(a > b);System.out.println(a < b);System.out.println(a b);char c1 A;char…

互联网舆情监测公司监测哪些内容,TOOM北京舆情监测公司

互联网舆情监测公司是一种提供舆情监测、分析和管理服务的公司&#xff0c;其业务主要涉及互联网舆情监测、数据分析、报告撰写、危机处理等方面。这些公司通过使用各种技术和工具&#xff0c;帮助客户监测他们在互联网上的声誉和品牌形象&#xff0c;并提供相应的建议和解决方…

前端基于 Docker 的 SSR 持续开发集成环境实践

项目收益 整体开发效率提升20%。加快首屏渲染速度&#xff0c;减少白屏时间&#xff0c;弱网环境下页面打开速度提升40%。 权衡 在选择使用SSR之前&#xff0c;需要考虑以下事项&#xff01; SSR需要可以运行Node.js的服务器&#xff0c;学习成本相对较高。对于服务器而言&a…

“就业”or“创业”,大学生毕业如何选择,校园市场是新出路?

据公开数据显示&#xff0c;2023届全国高校毕业生预计达到1158万人&#xff0c;同比增加82万人。规模和增量创历史新高。今年就业形势再次复杂严峻起来。 “就业难”这个词在疫情下的毕业季尤为明显。超过1000万人同时加入了争夺就业机会的行列&#xff0c;形成了庞大的求职阵容…

网络安全-靶场搭建

网络安全-靶场搭建 靶场就是给你练习用的&#xff0c;因为如果你直接用其他网站搞会把他搞炸的&#xff08;犯法的&#xff09; 简单概括&#xff1a;把靶场文件放到Phpstudy的网站&#xff0c;放到根目录里面 要用到之前下载的phpstudy 然后开启mysql和apache&#xff0c;默…

【2023】Prometheus-Blackbox_exporter使用

目录1.下载及安装blackbox_exporter2.修改配置文件设置监控内容2.1.使用http方式作为探测3.与prometheus集成4.导入blackbox仪表盘进行观测1.下载及安装blackbox_exporter 下载安装包 wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.23.0/black…

企业现代化管理模式中,数据指标体系是什么

当前时代&#xff0c;数据已经成为了构建现代社会的重要元素&#xff0c;渗透到人们生活的方方面面。在商业世界中&#xff0c;数据的传播应用更是按下了加速键&#xff0c;在短时间内就让各行各业的企业开始围绕数据进行信息化、数字化转型&#xff0c;把数据当作企业重要的战…

前端原生 CSS 跑马灯效果,无限轮播(横竖版本,带渐变遮罩,简单实用)

一、横版跑马灯 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wid…

Redis入门到实战-数据结构 (四、原理篇)

一、动态字符串SDS 我们都知道Redis中保存的Key是字符串&#xff0c;value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。 不过Redis没有直接使用C语言中的字符串&#xff0c;因为C语言字符串存在很多问题&#xff1a; 获取字符串长度的需要通过…

计算机网络之http07 http2,http3

HTTP1.2 http1.2都做了哪些优化 (1)头部压缩 使用HPACK压缩头部 头部冗长&#xff0c;大量重复字段 &#xff08;2&#xff09;二进制帧 将报文头部和内容字符编码改为二进制格式 字符编码未压缩 &#xff08;3&#xff09;并发传输 解决h1.1 队头阻塞问题&#xff0c;多车道 …

opencv通道的分离与合并

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

腾讯云 cos 字体在CDN上跨域处理

问题描述&#xff1a;项目中用到了字体的静态资源&#xff0c;把静态资源放到了腾讯云对象存储提供的 COS 上&#xff0c;同时启用它的CDN来加速。但是&#xff0c;调试的过程中发现报错&#xff1a;CSS加载字体跨域了&#xff0c;字体图标无法正常显示。 原因&#xff1a;字体…

torch.grid_sample

参考&#xff1a; 双线性插值的理论Pytorch grid_sample解析PyTorch中grid_sample的使用方法pytorch中的grid_sample()使用 查阅官方文档&#xff0c;TORCH.NN.FUNCTIONAL.GRID_SAMPLE grid_sample的函数签名如下所示&#xff0c;torch.nn.functional.grid_sample(input, gr…

Java设计模式总叙

文章目录基本概念设计模式的七大原则设计模式有哪些高频使用&经典的设计模式创建型-工厂方法模式创建型-建造者模式结构型-代理模式结构型-外观模式行为型-策略模式行为型-模板方法补充UML类图关系参考基本概念 使得代码编写真正工程化&#xff0c;它是软件工程的基石。 …