每日一题——表现良好的最长时间段

152 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 14 天,点击查看活动详情


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 <= 104
  • 0 <= hours[i] <= 16

思路

这道题目很容易想到用滑动窗口来解决,但是这是一个陷阱,因为我们无法确定何时该将左边界右移,这样就会错过最优解。

正确的思路是使用前缀和来求解,我们要求的是从每一个 0 开始的最大前缀和的长度,可以使用 HashMap 来存储每个位置的前缀和,每次遍历时将当前位置的前缀和记录下来。

若当前前缀和为正数,则表示存在符合条件的区间,若当前前缀和为非正值,说明从 0 到当前位置不符合条件,此时,我们可以去寻找是否存在更小的一个区间,即前缀和为 sum - 1 的位置,若存在位置 j,则 j + 1 到 i 位置的区间是可以符合条件的。

题解

class Solution {
    public int longestWPI(int[] hours) {
        int n = hours.length;
        Map<Integer, Integer> map = new HashMap<>();
        int max = 0;
        int sum = 0;
        for(int i = 0; i < n; i++) {
            sum += hours[i] > 8? 1: -1;
            if(sum > 0) {//存在从0到i的表现良好时间段
                max = Math.max(max, i + 1);
            }else {
                if(map.containsKey(sum - 1)) {//找到上一个表现更差的时间
                    max = Math.max(max, i - map.get(sum - 1));
                }
            }
            if(!map.containsKey(sum)) {
                map.put(sum, i);
            }
        }
        return max;
    }
}

如果你有其他的思路或者更好的解法,亦或者你发现了文章出现了错误或有不足,欢迎在评论区和我交流,我看到了一定会回复。

写文章不易,如果你觉得文章对你有帮助,麻烦点一下点赞、收藏,你的支持是我写文章的最大动力!