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