1343. 大小为 K 且平均值大于等于阈值的子数组数目

题目分类:数组;

题目描述

给你一个整数数组 arr 和两个整数 k 和 threshold 。
请你返回长度为 k 且平均值大于等于 threshold 的子数组数目。

想看原题请狠戳这个

分析过程

首先我自己出个实例:

设这个数组为[1, 3, 4, 6, 2, 5],k为3,threshold为4,求这个结果。

我们应该怎么想?

看到这个题的第一眼我感觉就是要用滑动窗口,因为这个是数组,而且是分段,而且题目还说明了必须是子串(连续的一部分数组)的和要符合要求才算。加上个窗口后要干嘛?当然是移动鸭!

首先是初始化

注意:我这里是用的 k×threshold 来作为判断条件,跟题目里说的平均数意思一样,只不过我没用除法,直接用 k 个数的和跟 k×threshold 做比较


很遗憾,前三个数的和为8,比12小,并不符合要求。

移动窗口


这里我不用每次计算窗口内的值的和,因为每次移动窗口,只会添加一个新数(绿色)丢弃一个旧数(黄色),我直接用原有的sum减去丢弃的数,再加上新增的数就可以了。

这里我可以设置一个指针pos,让pos每次指向新增的数,所以pos的初始值一定为k,也就是指向窗口后面的第一个数;而这时候只需要用一个for循环,将数组从0遍历到arr.length - k就行了。

Words are cheap, show me the code.

千言万语顶不上看一眼源码,来来来,上代码:

public int numOfSubarrays(int[] arr, int k, int threshold) {
   
        int sum = 0, res = 0;
        //进行初始化
        for (int i = 0; i < k; i++) {
   
            sum += arr[i];
        }
        //首先判断第一个窗口是否符合要求
        if (sum >= threshold * k) {
   
            res++;
        }
        //pos指向窗口内将要新加入的数
        int pos = k;
        for (int j = 0; j < arr.length - k; j++) {
   
            if ((sum += arr[pos] - arr[j])  >= threshold * k) {
   
                res++;
            }
            //指针继续后移
            pos++;
        }
        return res;
    }

这时候结合动图,应该就好理解了。