LeetCode题解:1124. 表现良好的最长时间段,哈希表,详细注释

61 阅读2分钟

原题链接: leetcode.cn/problems/lo…

模拟一次统计过程:

  1. 假设hours = [6, 6, 0, 9, 9, 9, 9, 3]
  2. 根据题意,我们可以将超过8小时的工作日统计为1分,其余统计为-1
  3. 并且计算出每一天能获得的总分,如下
原始数组: [ 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]

分析统计结果

  1. 对于索引i = 6,它的总分大于0,索引0 ~ 6,共7个数都是“表现良好的时间段”。可得出规律:只要总分大于0,索引从0i都是“表现良好的时间段”
  2. 对于索引i = 4,虽然它的分数是-1,但索引1 ~ 4,都是“表现良好的时间段”。可因此得出规律:如果索引小于等于0,从第一次出现总分为sum - 1的位置(sum - 1不计入长度,计入总分就为0,不满足条件),到i的长度,都是”表现良好的时间段“。虽然我们也可以取从sum - 2i的长度,但这个长度肯定比sum - 1i
  3. 为了找到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
};