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

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

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

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

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= hours.length <= 10^4
  • 0 <= hours[i] <= 16


提示 1

Make a new array A of +1/-1s corresponding to if hours[i] is > 8 or not. The goal is to find the longest subarray with positive sum.


提示 2

Using prefix sums (PrefixSum[i+1] = A[0] + A[1] + ... + A[i]), you need to find for each j, the smallest i < j with PrefixSum[i] + 1 == PrefixSum[j].

解法:前缀和 + 哈希表

我们记工作小时数大于 8 的为 1 分,小于等于 8 的为 −1 分,原问题由求解最长的「表现良好的时间段」长度转变为求解分数和大于 0 的最长区间长度。

我们使用前缀和 s,对于某个下标 i(从 0 开始),我们期待找到最小的 j (j<i),满足 s[j]<s[i]。接下来,我们按照 s[i] 是否大于 0 来分情况讨论:

  • 如果 s[i]>0,那么前 i+1 项元素之和大于 0,表示有一个长度为 i+1 的大于 0 的区间。
  • 如果 s[i]<0,我们在前面试图寻找一个下标 j,满足 s[j]=s[i]−1。如果有,则表示区间 [j+1,i] 是我们要找的以 i 结尾的最长区间。

为什么第 2 种情况要找 s[i]−1,而不是 s[i]−2 或更小的一项?因为在本题中分数只有 1 或者 −1,如果前缀和数组中在 i 之前要出现小于 s[i] 的元素,它的值一定是 s[i]−1。也就是说当 s[i]<0 时,我们要找到 j 使得 s[j]<s[i],如果有这样的 j 存在,这个 j 一定满足 s[j]=s[i]−1。

实现过程中,我们可以使用哈希表记录每一个前缀和第一次出现的位置,即可在 O(1) 的时间内判断前缀和等于 s[i]−1 的位置 j 是否存在。

类似题型:LeetCode 面试题 17.05. 字母与数字-CSDN博客 

LeetCode 1546. 和为目标值且不重叠的非空子数组的最大数目-CSDN博客

Java版:

class Solution {
    public int longestWPI(int[] hours) {
        int maxLength = 0;
        int presum = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < hours.length; i++) {
            presum += hours[i] > 8 ? 1 : -1;
            if (presum > 0) {
                maxLength = i + 1;
            } else {
                if (map.containsKey(presum - 1)) {
                    maxLength = Math.max(maxLength, i - map.get(presum - 1));
                }
            }
            if (!map.containsKey(presum)) {
                map.put(presum, i);
            }
        }
        return maxLength;
    }
}

Python3版:

class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        maxLength = 0
        dic = dict()
        presum = 0
        for i, hour in enumerate(hours):
            presum += 1 if hour > 8 else -1
            if presum > 0:
                maxLength = i + 1
            else:
                if presum - 1 in dic:
                    maxLength = max(maxLength, i - dic[presum - 1])
            if presum not in dic:
                dic[presum] = i 
        return maxLength
        

复杂度分析

  • 时间复杂度:O(n),其中 n 为 hours 的长度。

  • 空间复杂度:O(n),其中 n 为 hours 的长度。

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值