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;
}
这时候结合动图,应该就好理解了。