代码仓库:Github | Leetcode solutions @doubleZ0108 from Peking University.
- 解法1(T53% S51%):题目看起来简单,但想起来还是很难的,最后还是看了很多题解才大致明白。因为工作时间只有两种可能,因此转为二值数组会简单一点,将>8的转为+1,<8的变为-1,然后求取前缀和,那问题就转化为找到距离最远的i和j,使得s[j]-s[i]为正,二者的这个减法就相当于i~j区间内的求和,如果求和>0则代表着这个区间段内工作>8小时的天数更多,但也要分两种情况
- 如果第i位的前缀和>0,则代表从0到i一定能构成表现良好的区间,而且随着i的循环,i肯定是在变大的,直接更新就好,这个比较好理解(相当于>8的天一定比<8的多,才可能让前缀和为正)
- 但如果第i位的前缀和<0,那就意味着从0开始算的话<8的天数更多,所以左边边界肯定要往后,那具体要往后多少呢?因为我们已经将原数组转换为只有+1和-1的数组,因此如果当前位的前缀和为-x的情况下,一定在此之前存在-x-1这个数,因为每次我们都只能+1或者-1,而我能从-x-1变到现在第i位的-x,那一定证明这个区间段里有更多的工作>8小时的天。因此具体实现的时候我把每一个<0的前缀和下标都保存到哈希表中,当发现一个位置的前缀和位-x,我就找-x-1在不在哈希表中,如果在那二者的下标差就是结果,注意不要更新已经存在于哈希表中的key-val,因为本题是要求最大的长度
class Solution:
def longestWPI(self, hours: List[int]) -> int:
hours = [1 if x>8 else -1 for x in hours]
for i in range(1, len(hours)):
hours[i] += hours[i-1]
res = 0
table = {}
for i in range(len(hours)):
if hours[i] > 0:
res = i+1 # 如果某个位置 前缀和>0 则代表从头到这里就构成了一个良好时间段
else:
if hours[i] not in table:
table[hours[i]] = i
if hours[i]-1 in table:
res = max(res, i-table[hours[i]-1])
return res