开启掘金成长之旅!这是我参与「掘金日新计划 · 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 <= 1040 <= 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;
}
}
如果你有其他的思路或者更好的解法,亦或者你发现了文章出现了错误或有不足,欢迎在评论区和我交流,我看到了一定会回复。
写文章不易,如果你觉得文章对你有帮助,麻烦点一下点赞、收藏,你的支持是我写文章的最大动力!