Loading

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

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

题目链接:1124.表现良好的最长时间段

前缀和

什么是前缀和:【算法】前缀和

我们计工作时间超过8小时为1,否则为-1,那么所谓的“表现良好的时间段”就是和大于0的区间。

暴力-0

最简单的方法是遍历所有可能的区间,判断是否和大于零,并返回和大于零的区间最大长度。

暴力-1

对暴力-0进行优化,由于是寻找最长的区间,固定区间左端,右端从大到小遍历,只要找到一个就行,然后左端移动,重复进行,则每一个左端对应一个长度,其中最长的即为所求。

暴力-2

继续优化,在循环中动态更新结果result,在大循环中,如果剩余的总长度不够result,不可能再找出比result更大的结果,直接返回。

暴力-3

我们也可以固定右端right,这样的话并没有对算法进行优化,但是更好理解。

我们用数组s表示前缀和,score表示正负一数组,则 \(\sum_{j=0}^{i-1}score[j]=s[i]\)

那么我们的目标是找到左端left和右端right,使得 \(s[right]-s[left]>0\) 并且 \(right-left\) 最大。

由于我们固定了右端,初始情况下,\(left\) 为0,那么只要 \(s[right]>0\),那么对应的最长长度为 \(right\),而且这种情况下,后续移动右端将不会有更长的区间,直接判断 \(right\)\(result\) 中更大的,如果 \(right\) 已经比 \(result\) 小,也是同理,直接返回 \(result\)

如果 \(s[right]<0\),则需要找到最小的 \(left\),使得 \(left<right\)\(s[right]>s[left]\)。由于s中的元素都是-1和1,当left从0增大,\(s[right]-s[left] < 0\) 每次以连续整数向 \(s[right]-s[left] > 0\) 变化,则最小满足条件的left一定有 \(s[right]-s[left] == 1\)。即,寻找最小的 \(left<right\) 使得 \(s[right]-s[left] == 1\),和【LeetCode】1.两数之和类似,使用hash表进行优化。

class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        result = 0
        score = 0
        hashmap = {}
        for i in range(len(hours)):
            score = score + (1 if hours[i] > 8 else -1)
            if score not in hashmap:
                hashmap[score] = i
            if score > 0:
                result = max(i+1, result)
            elif score-1 in hashmap:
                result = max(i-hashmap[score-1], result)
        return result
posted @ 2023-02-14 22:36  杨谖之  阅读(27)  评论(0编辑  收藏  举报