表现良好的最长时间段

226 阅读1分钟

表现良好的最长时间段

给你一份工作时间表 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

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/lo… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

给我们一个考勤表,让我们求该考勤表“表现良好的时间段”的最大长度。

1.png

当工作小时数>8时,“表现良好时间段”的次数+1,当工作小时数<=8时,“表现良好时间段”的次数-1,结合题意,我们需要求的就是:某个时间段内,“表现良好时间段”的次数>0,且这个时间段,需要取最长的一个时间段,用前缀和记录起来

3.png

我们需要获取表现良好时间段的次数>0的时间段,且长度尽可能长,即我们需要:前缀和>0,且长度尽可能长

且前缀和一定是连续的,比如当前前缀和为‘1’,下一个前缀和必定是‘0’或者‘2’

代码


var longestWPI = function (hours) {
    let preSum = new Array(hours.length + 1).fill(0);
    for (let i = 0; i < hours.length; i++) {
        // 遍历数组,保存前缀和
        if (hours[i] > 8) preSum[i + 1] = preSum[i] + 1;
        else preSum[i + 1] = preSum[i] - 1;
    }
    let stack = [];
    stack.push(0);
    for (let i = 1; i < preSum.length; i++) {
        // 取到前缀和小于0的值的下标(表现不良好的天数>表现良好的天数)
        if (preSum[i] < preSum[stack[stack.length - 1]]) stack.push(i);
    }
    let max = 0;
    for (let i = preSum.length - 1; i > max; i--) {
        while (stack.length && preSum[stack[stack.length - 1]] < preSum[i]) {
            max = Math.max(max, i - stack.pop());
        }
    }
    return max;
};