原题链接: leetcode.cn/problems/lo…
模拟一次统计过程:
- 假设
hours = [6, 6, 0, 9, 9, 9, 9, 3] - 根据题意,我们可以将超过8小时的工作日统计为
1分,其余统计为-1分 - 并且计算出每一天能获得的总分,如下
原始数组: [ 6, 6, 0, 9, 9, 9, 9, 3]
数组索引: [ 0, 1, 2, 3, 4, 5, 6, 7]
每日分数: [-1, -1, -1, 1, 1, 1, 1, -1]
统计总分: [-1, -2, -3, -2, -1, 0, 1, 0]
分析统计结果
- 对于索引
i = 6,它的总分大于0,索引0 ~ 6,共7个数都是“表现良好的时间段”。可得出规律:只要总分大于0,索引从0到i都是“表现良好的时间段” - 对于索引
i = 4,虽然它的分数是-1,但索引1 ~ 4,都是“表现良好的时间段”。可因此得出规律:如果索引小于等于0,从第一次出现总分为sum - 1的位置(sum - 1不计入长度,计入总分就为0,不满足条件),到i的长度,都是”表现良好的时间段“。虽然我们也可以取从sum - 2到i的长度,但这个长度肯定比sum - 1到i短 - 为了找到
sum - 1的位置,我们需要缓存每个sum对应的索引i
/**
* @param {number[]} hours
* @return {number}
*/
var longestWPI = function(hours) {
let map = new Map() // 用于缓存sum和索引
let sum = 0 // 缓存当前位置的总分
let res = 0 // 缓存直到当前位置的最大长度
for (let i = 0; i < hours.length; i++) {
// 计算当前位置的总分,工作时间大于8记1分,其余记-1
sum += hours[i] > 8 ? 1 : -1
// 如果sum大于0,表示从索引0到i的数量都为”表现良好时间段“
if (sum > 0) {
// 始终取最大值
res = Math.max(res, i + 1)
} else {
// 如果sum小于等于0,从第一个出现sum - 1总分的位置
// 到当前索引为止的长度,为”表现良好时间段“
// 但出现sum - 1总分的索引不计入长度,因为计入的话总分就为0了
// 如果是第一次出现sum - 1,由于此时sum <= 0,因此没有”表现良好时间段“,无需计算
if (map.has(sum - 1)) {
res = Math.max(res, i - map.get(sum - 1))
}
}
// 缓存每个结果的索引,供后续查询用
// 并且每个索引只缓存一次,保证”表现良好时间段“为最大
if (!map.has(sum)) {
map.set(sum, i)
}
}
return res
};