当前位置: 首页 > news >正文

算法随笔_50: 表现良好的最长时间段

上一篇:算法随笔_49: 有效的括号-CSDN博客

=====

题目描述如下:

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

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

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

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

示例 1:

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

示例 2:

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

=====

算法思路:

根据题目描述,我们发现,判断“劳累的天数”是严格大于“不劳累的天数”,可以转化为一个求和问题。我们把大于8的元素置为1,小于等于8的元素置为-1,那么某个区间的元素和大于等于1时,就表示了“劳累的天数”严格大于“不劳累的天数”。

那么题目的要求返回表现良好时间段的最大长度,就变为了求元素和大于0的最长区间

对于计算区间元素和,有一个常用的方法: 前缀和

我们设数组nums,pre_sum。

pre_sum[i]表示nums的[0, i]区间的元素和。

pre_sum[j]表示nums的[0, j]区间的元素和。

i < j,因此[i+1, j]区间的元素和就是这两个前缀和的差,即,pre_sum[j] - pre_sum[i]。

介绍了计算区间元素和的方法,我们再来看一下如何寻找最长的区间。

我们先考虑以某个索引 j 为某个区间的右端点,那么如何求出这个区间的最左端点 i 呢?显然最左端点应该出现在从左往右数的第一个使pre_sum[j] - pre_sum[i]>0的索引处。但大于0的值有很多,我们选取哪个值来计算pre_sum[i]呢?我们选择1即可。假如pre_sum[j]=-5,我们选第一次出现的pre_sum[i]=-6,因为如果选择pre_sum[i]=-7,-8等。会导致索引i更靠近右侧,肯定不是最左端点。因此我们找到第一个前缀和为pre_sum[j]-1处的索引即可。

我们枚举所有索引,并找到它们各自的最长区间,最后取它们的最大值即为最终答案。

基本的算法如下:

1. 我们设res为最大区间长度,初始值为0。从左往右枚举数组hours,同时计算当前索引的前缀和pre_sum。如果hours[i]>8,pre_sum加1,否则减1。

2. 把第一次出现的pre_sum存入字典sum2ind中,值为索引i,即,sum2ind[pre_sum]=i。

3.  判断pre_sum-1是否存在于sum2ind,如果存在,用当前索引i减去sum2ind[pre_sum -1]。这就是以当前索引 i 为右端点的最长区间长度seg_len。同时更新res=max(res, seg_len) 。

对于pre_sum大于0的情况,代码实现时有两点需要注意:

1.  我们把前缀和为0的索引设置在-1处,即sum2ind[0]=-1。以方便后面的计算。

2.  当前缀和大于0时,我们统一把pre_sum置为1。这并不影响最终的结果,因为当前缀和大于0时,它的最左端点就是sum2ind[0]=-1处。我们把它置为1,也是为了方便计算前面算法提到的步骤3。当所有pre_sum > 0 时,pre_sum -1都能定位到sum2ind[0]=-1处。

此算法的时间复杂度为O(n) 。下面是代码实现:

class Solution(object):
    def longestWPI(self, hours):
        """
        :type hours: List[int]
        :rtype: int
        """
        sum2ind = {0: -1}
        pre_sum = 0
        res = 0
        
        for i, hour in enumerate(hours):
            pre_sum += 1 if hour > 8 else -1
            k = 1 if pre_sum > 0 else pre_sum
            if k - 1 in sum2ind:
                res = max(res, i - sum2ind[k - 1])
                
            if k not in sum2ind:
                sum2ind[k] = i
        
        return res

关键词: 前缀和

相关文章:

  • matlab齿轮传动
  • unity学习36:老版的动画 Animation
  • pytorch训练五子棋ai
  • Azure上基于OpenAI GPT-4模型验证行政区域数据的设计方案
  • deepSeek本地部署,详细教程,Ollama安装
  • 机器学习入门-读书摘要
  • 数据结构 树的存储和遍历
  • 一口气入门前端——HTML5入门
  • 内网穿透简单使用
  • QEMU参数与使用
  • nginx播放视频(auth_request鉴权)
  • 人工智能行为识别之slowfast源码解读
  • Linux Mem -- MTE in AArch64 Linux
  • 树莓集团全国拓展:产业园服务与人才培养的协同发展
  • 【开源项目】数字孪生武汉~超经典智慧城市CIM/BIM数字孪生可视化项目——开源工程及源码
  • DeepSeek操作Excel,实现图表自动化生成
  • 实用教程:用微服务搭建你的2025项目
  • HDFS应用-后端存储cephfs-文件存储和对象存储数据双向迁移
  • Node.js NativeAddon 构建工具:node-gyp 安装与配置完全指南
  • uni-app中常用的指令语句有哪些?
  • 吴双评《发展法学》|穷国致富的钥匙:制度,还是产业活动?
  • 消费维权周报丨上周涉汽车类投诉较多,涉加油“跳枪”等问题
  • 官方数据显示:我国心血管疾病患者已超3亿人
  • 特朗普政府涉税改法案遭众议院预算委员会否决
  • 泽连斯基:俄代表团级别低,没人能做决定
  • 上海国际珠宝时尚功能区未来三年如何建设?六大行动将开展