这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战
题目
给你一个下标从 0 开始的数组 nums
,数组中有 n
个整数,另给你一个整数 k
。
半径为 k 的子数组平均值 是指:nums
中一个以下标 i
为 中心 且 半径 为 k
的子数组中所有元素的平均值,即下标在 i - k
和 i + k
范围(含 i - k
和 i + k
)内所有元素的平均值。如果在下标 i
前或后不足 k
个元素,那么 半径为 k 的子数组平均值 是 -1
。
构建并返回一个长度为 n
的数组 avgs
,其中 avgs[i]
是以下标 i
为中心的子数组的 半径为 k 的子数组平均值 。
x
个元素的 平均值 是 x
个元素相加之和除以 x
,此时使用截断式 整数除法 ,即需要去掉结果的小数部分。
- 例如,四个元素
2
、3
、1
和5
的平均值是(2 + 3 + 1 + 5) / 4 = 11 / 4 = 3.75
,截断后得到3
。
示例
输入: nums = [7,4,3,9,1,8,5,2,6], k = 3
输出: [-1,-1,-1,5,4,4,-1,-1,-1]
解释:
- avg[0]、avg[1] 和 avg[2] 是 -1 ,因为在这几个下标前的元素数量都不足 k 个。
- 中心为下标 3 且半径为 3 的子数组的元素总和是:7 + 4 + 3 + 9 + 1 + 8 + 5 = 37 。
使用截断式 整数除法,avg[3] = 37 / 7 = 5 。
- 中心为下标 4 的子数组,avg[4] = (4 + 3 + 9 + 1 + 8 + 5 + 2) / 7 = 4 。
- 中心为下标 5 的子数组,avg[5] = (3 + 9 + 1 + 8 + 5 + 2 + 6) / 7 = 4 。
- avg[6]、avg[7] 和 avg[8] 是 -1 ,因为在这几个下标后的元素数量都不足 k 个。
复制代码
输入: nums = [100000], k = 0
输出: [100000]
解释:
- 中心为下标 0 且半径 0 的子数组的元素总和是:100000 。
avg[0] = 100000 / 1 = 100000 。
复制代码
输入: nums = [8], k = 100000
输出: [-1]
解释:
- avg[0] 是 -1 ,因为在下标 0 前后的元素数量均不足 k 。
复制代码
提示
n == nums.length
1 <= n <= 10^5
0 <= nums[i], k <= 10^5
解题思路
滑动窗口
要计算一段长度为k
的子数组平均值,滑动窗口无疑是一个很好的方式,固定窗口长度k * 2 + 1
,统计出区间总和,再求得平均值avg
之后填入到中心位置对应索引处即可。然后向右滑动,增加右边元素,减去左边元素,继续重复前面的求和取平均值步骤。
class Solution {
public int[] getAverages(int[] nums, int k) {
// 边界判断
if(k == 0){
return nums;
}
int n = nums.length;
int[] ans = new int[n];
Arrays.fill(ans, -1);
if(n < k * 2 + 1){
return ans;
}
// 由于n的取值范围比较大,这里需要采用long类型来统计区间和
long sum = 0;
int left = 0, right = 0;
// 初始化窗口区间和,这里要预留最右边一位数
while(right - left < k * 2){
sum += nums[right++];
}
while(right < n){
// 加上最右边的元素
sum += nums[right++];
// 求平均值,将其赋值给中间点
ans[left + k] = (int)(sum / (k * 2 + 1));
// 减去最左边的元素
sum -= nums[left++];
}
return ans;
}
}
复制代码
复杂度分析
- 时间复杂度:
- 空间复杂度:
最后
文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!
如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!
题目出处: