leetcode 643. 子数组最大平均数 I ------滑动窗口篇六,前缀和篇二
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 643. 子数组最大平均数 I ------滑动窗口篇六,前缀和篇二相关的知识,希望对你有一定的参考价值。
暴力法思想
从数组头部开始,依次枚举所有长度为k的连续子数组,对其求和,从中找出最大值
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k)
{
int l = 0, r = k;
double res = INT_MIN;
while (r <=nums.size())
{
//注意:左闭右开的区间
double sum=accumulate(nums.begin()+l, nums.begin() + r, 0);
res = max(res, sum/k);
l++, r++;
}
return res;
}
};
暴力法的优化思路
思路:
每次的子数组不能重新计算,会超时, 采用减去上一次的首段再加上新的尾部来计算
代码:
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k)
{
int l = 0, r = k;
int sum, res;
sum =res = accumulate(nums.begin() + l, nums.begin() + r, 0);
while (r <nums.size())
{
sum = sum + nums[r]-nums[l];
res = max(res, sum);
l++, r++;
}
return (double)res/k;
}
};
滑动窗口
题目可以抽象成长度固定为 k 的滑动窗口。当每次窗口右移的时候,需要把右边的新位置 加到 窗口中的 和 中,把左边被移除的位置从窗口的 和 中 减掉。这样窗口里面所有元素的 和 是准确的,我们求出最大的和,最终除以 k 得到最大平均数。
这个方法只用遍历一次数组。
需要注意的是,需要根据 i 的位置,计算滑动窗口是否开始、是否要移除最左边元素:
- 当 i >= k 时,为了固定窗口的元素是 k 个,每次移动时需要将 i - k 位置的元素移除。
- 当 i >= k - 1 时,最左边第一个滑动窗口内的元素刚好 k 个,开始计算滑动窗口的最大和。
代码:
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k)
{
int sum=0, res = INT_MIN;
for (int i = 0; i < nums.size(); i++)
{
sum += nums[i];
if (i >= k)
sum -= nums[i - k];//当前滑动窗口的长度超了一个,减去最左边的多出的元素
if (i >= k - 1)
res = max(res, sum);
}
return (double)res/k;
}
};
前缀和
今天题目让求最大平均数,由于 k 是不变的,因此可以先求区间的最大和,然后再除以 k。
求区间的和可以用 preSum。preSum 方法还能快速计算指定区间段 i ~ j 的元素之和。它的计算方法是从左向右遍历数组,当遍历到数组的 i 位置时,preSum 表示 i 位置左边的元素之和。
假设数组长度为 N,我们定义一个长度为 N+1 的 preSum 数组,preSum[i] 表示该元素左边所有元素之和(不包含当前元素)。然后遍历一次数组,累加区间 [0, i) 范围内的元素,可以得到 preSum 数组。
利用 preSum 数组,可以在 O(1) 的时间内快速求出 nums 任意区间 [i, j] (两端都包含) 的各元素之和。
sum(i, j) = preSum[j + 1] - preSum[i]
对于本题,可以先遍历一次,求数组每个位置的 preSum,然后再遍历一次,求长度为 k 的每个区间的最大和。最终除以 k 得到最大平均数。
代码:
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k)
{
//在原数组上直接求出前缀和数组,这样可以节省空间消耗
for (int i = 1; i < nums.size(); i++)
nums[i] += nums[i - 1];
int res = nums[k-1];
for (int i = k; i < nums.size(); i++)
res = max(res, nums[i] - nums[i - k]);
return (double)res/k;
}
};
以上是关于leetcode 643. 子数组最大平均数 I ------滑动窗口篇六,前缀和篇二的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode题目记录-643. 子数组最大平均数 I(C++代码实现)
leetcode 643. 子数组最大平均数 I ------滑动窗口篇六,前缀和篇二
LeetCode 643. Maximum Average Subarray I (最大平均值子数组之一)
解题报告Leecode 643. 子数组最大平均数 I——Leecode 刷题系列