[路飞] 34——leetcode - [1124] 表现良好的最长时间段

103 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

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

题目分析

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

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

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

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

思路讲解

我们将工作时长大于8小时的那一天记作为1,小于等于八小时的那一天记为-1。这样我们就得到了一组只有1和-1的数组。我们从第一天到第n天的和如果大于0,就证明从第一天到第n天这段区间是表现良好的。所以我们可以计算下从第一天开始到第n天的和,也就是我们的前缀和。

示例

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

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

代码

/*
 * @lc app=leetcode.cn id=1124 lang=javascript
 *
 * [1124] 表现良好的最长时间段
 */

// @lc code=start
/**
 * @param {number[]} hours
 * @return {number}
 */
var longestWPI = function (hours) {
  // 1.将大于8的认为是1 小于等于8的为-1, 然后求整个数组的前缀和
  // 下标【i, j】:表示天数  preSum[i], preSum[j]: 前缀和元素,表示是否是良好的时间段
  let preSum = new Array(hours.length + 1).fill(0) // 定义一个前缀和数组, 默认值设置为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
  }
  // 2.生成一个单调栈记录i的备选项
  let stack = [] // 定义一个栈记录下标数组
  stack.push(0)
  for (let i = 0; i < preSum.length; i++) {
    if (preSum[i] < preSum[stack[stack.length - 1]]) stack.push(i) // 找到了更小的, 记录下角标
  }
  let max = 0; // j - i
  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
};
// @lc code=end