Leetcode 1124. 表现良好的最长时间段

2025/04/12

1124. 表现良好的最长时间段

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

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

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

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

示例 1:

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

class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        '''
        首先,将原数组中的6变为-1,9变为1,原问题变为 求和大于0的连续数字的最大长度
        这样一来,思路就 和 525. 连续数组 这道题(求连续数字和==0的最大长度)类似

        原数组      9  9   6  0  6   6  9
        转化后      1  1  -1 -1 -1  -1  1
        前i项的和   1  2   1  0  -1  -2 -1 

        记转化后的数组的前i项和为s, 前i项的和 与i的对应关系记录在c中(注意:这里的前i项的和是第一次出现的)
        遍历数组hours,当枚举到第i项时,计算前i项数字的和 s
        1.如果s>0,那么,在当前的前i项中,最长满足条件的子数组长度就为i+1
        2.否则,查看s-1是否在前i-1项中出现过,也就是s-1是否在c存在。
        因为如果出现过,那么和为s-1的连续数组 与 i之间的数字和就为 s -(s-1)=1 > 0,即中间的数字也是符合条件的。

            那么,这里为什么不继续查看s-2 s-3是否在前i-1项出现过呢?
            答案是:如果s-1没有出现过的话,s-2 s-3就不会先出现,也就是s-1会出现在s-2 s-3的前面。

            因为数组中只有数字 1 -1,在s<=0的情况下,s-1 s-2 ...都是小于0的,那么,在变小的过程中,一次只能减少1,他们出现的顺序必然是s-1 s-2 ...

            而为了保证我们找到的中间这段数字的长度是最大的,我们查看前面的s-1的位置即可
            如果c中出现过s-1,设前j项连续数组和为s-1,那么j+1~i之间的连续数字就符号条件,更新答案为res = max(res, i - c[s-1])
        3.如果s不在c中的话,表示当前的连续数字和也是第一次出现,将 s-->i 记录到c中

        遍历完数组之后,得到答案
        
        '''
        s,r=0,0
        n=len(hours)
        c={}
        for i in range(n):
            s+= 1 if hours[i]>8 else -1
            if s>0:
                r=i+1
            elif s-1 in c:
                r = max(r,i-c[s-1])
            elif s not in c:
                c[s]=i
        return r

Post Directory