抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

用到了滑动窗口

LeetCode题目链接:

1343. 大小为 K 且平均值大于等于阈值的子数组数目 - 力扣(LeetCode) (leetcode-cn.com)

给你一个整数数组 arr 和两个整数 k 和 threshold 。

请你返回长度为 k 且平均值大于等于 threshold 的子数组数目。

示例 1:

输入:arr = [2,2,2,2,5,5,5,8], k = 3, threshold = 4
输出:3
解释:子数组 [2,5,5],[5,5,5] 和 [5,5,8] 的平均值分别为 4,5 和 6 。其他长度为 3 的子数组的平均值都小于 4 (threshold 的值)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

因为是子数组,不是子序列(子序列不管顺序位置,子数组连续的),可以用滑动窗口

假装有个窗口,他只能装k个值,没有元素的时候往里填满k个,算一下平均值够不够threshold,够了就count++。

因为已经满了,就把开头的第一个元素删掉,继续装进来一个继续算。

这样就不用每次都取k个元素挨个算,代价小一点。

function solution(arr: number[], k: number, threshold: number) {
  let sum = 0,
    count = 0;
  // 先将前k个元素"填满"
  for (let i = 0; i <= k - 1; i++) {
    sum += arr[i];
  }
  // 看看最开始的k个元素符不符合条件
  if (sum / k >= threshold) {
    count++;
  }
  // 继续迭代后面的元素
  for (let i = k; i < arr.length; i++) {
    // 每次把开头的元素移出窗口
    sum -= arr[i - k];
    sum += arr[i];
    if (sum / k >= threshold) {
      count++;
    }
  }
  return count;
}

第一次写的有点简单,写到一个for循环里吧!

function solution(arr: number[], k: number, threshold: number) {
  let sum = 0,
    count = 0;

  for (let i = 0; i < arr.length; i++) {
    sum += arr[i];
    if (i >= k) {
      sum -= arr[i - k];
    }
    if (sum / k >= threshold && i >= k - 1) {
      count++;
    }
  }
  return count;
}

把第一次要干的都过滤出来了,看起来更加难以理解了点。。

函数式编程的话就不会有这个问题,一个循环干一件事,上面这样是函数式编程不推荐的。

这难道就是牺牲可读性,去附和性能吗,程序员倒是不快乐了。。

参考资料:

评论