题目简介 给你一份工作时间表
hours,上面记录着某一位员工每天的工作小时数。
我们认为当员工一天中的工作小时数大于8小时的时候,那么这一天就是【劳累的一天】。
所谓【表现良好的时间段】,意味着这段时间内,【劳累的天数】是严格 大于【不劳累的天数】。
请你返回【表现良好的时间段】的最大长度
示例
输入: hours = [9,9,6,0,6,6,9]
输出: 3
解释: 最长的表现良好时间段是 [9,9,6]。
解题思路 使用前缀+单调栈的方法。
1、前缀:已输入样例hours为例,将大于8的记为1,小于等于8的记为**-1**,得到source数组
2、对source数组计算前缀和presum = 【0,1,2,1,0,-1,-2,-1】
3、题目要求返回表现良好的最大长度,就是求得分1的个数大于-1的个数的最长的一段。
4、维护一个栈stack,存储presum中的元素索引,栈中索引指向的元素严格单调递减,比如presum中严格单调递减的元素是 0, -1, -2;所以stack= [0, 5, 6];
5、从后往前遍历presum数组,与栈顶索引指向元素比较,如果相减结果大于0,则一直出栈,直到不大0为止,然后更新当前最大宽度
代码实现
/**
* @param {number[]} hours
* @return {number}
*/
var longestWPI = function(hours) {
// 记录 hours 的长度
const n = hours.length;
// 创建source数组,长度和hours一致
const source = new Array(n).fill(0);
// 像source数组中记录当前得分
for(let i=0;i<n;i++){
if(hours[i] > 8) {
source[i] = 1;
}
else {
source[i] = -1;
}
}
// 创建 presum数组.
const presum = new Array(n + 1).fill(0);
// 计算前缀和
for (let i = 1; i < n + 1; i++){
presum[i] = presum[i - 1] + source[i - 1];
}
// 定义长度
let max = 0;
const stack = [];
// 向栈中添加递减元素额度下标
for (let i = 0; i < n + 1; i++){
if (!stack.length || presum[stack[stack.length-1]] > presum[i]) {
stack.push(i);
}
}
let i = n;
while (i > ans) {
while (stack.length && presum[stack[stack.length-1]] < presum[i]) {
ans = Math.max(ans, i - stack.pop());
}
i -= 1
}
return ans;
}