Given an integer array nums and an integer k, find the maximum average value of any continuous subarray of size k.
A subarray is a contiguous part of the array.
Return the maximum average value among all subarrays of size k.
If no subarray of size k exists, return 0.0.
Example 1
Input: nums = [1, 12, -5, -6, 50, 3], k = 4
Output: 12.75
Explanation: The subarray [12, -5, -6, 50] has the maximum sum 51.
So, the maximum average is 51 / 4 = 12.75.
Example 2
Input: nums = [5], k = 1
Output: 5.0
Explanation: The only subarray of size 1 is [5], so the maximum average is 5.0.
Example 3
Input: nums = [1, 2], k = 3
Output: 0.0
Explanation: No subarray of size 3 can be formed because the array has only 2 elements.
Brute Force Approach
Every valid starting index defines one contiguous subarray of size k. Calculating the sum of k consecutive elements from every starting index guarantees examination of all valid subarrays.
Dividing each sum by k produces the corresponding average. Overlapping subarrays contain common elements, so repeated calculation performs many unnecessary additions.
Algorithm
Store the array size in n and return 0.0 when
k <= 0orn < k.Initialize maxAverage with the smallest possible value to support arrays containing only negative numbers.
Traverse every valid starting index i from 0 to
n - k.Initialize currentSum with 0 and add elements from index i through
i + k - 1.Calculate currentAverage as
currentSum / kand update maxAverage when currentAverage is larger.Return maxAverage after processing every subarray of size k.
Dry Run
Maximum Average Subarray I Brute Force Dry Run.png
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: // Finds the maximum average by checking every subarray of size k. double findMaxAverage(vector<int>& nums, int k) { int n = nums.size(); // A valid subarray of size k cannot be formed. if (k <= 0 || n < k) { return 0.0; } double maxAverage = -DBL_MAX; // Treat every valid index as the start of a size-k subarray. for (int i = 0; i <= n - k; i++) { long long currentSum = 0; // Calculate the complete sum of the current subarray. for (int j = i; j < i + k; j++) { currentSum += nums[j]; } double currentAverage = static_cast<double>(currentSum) / k; // Keep the largest average found so far. if (currentAverage > maxAverage) { maxAverage = currentAverage; } } return maxAverage; }};int main() { vector<int> nums = {1, 12, -5, -6, 50, 3}; int k = 4; Solution solution; cout << fixed << setprecision(5) << solution.findMaxAverage(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N × K), where N represents the array size. Every valid starting index may require addition of K elements.
Space Complexity: O(1), because only loop indices, currentSum, currentAverage, and maxAverage require auxiliary storage.
Better Approach
A prefix sum array stores cumulative sums from the beginning of nums. The value at prefixSum[i] represents the sum of the first i elements.
For a subarray starting at index i and ending at index i + k - 1, subtracting prefixSum[i] from prefixSum[i + k] removes every element before index i. Each fixed-size subarray sum can therefore be calculated in constant time.
Algorithm
Store the array size in n and return 0.0 when
k <= 0orn < k.Create prefixSum with size
n + 1and initializeprefixSum[0]with 0.Traverse nums and calculate
prefixSum[i + 1] = prefixSum[i] + nums[i].Initialize maxAverage with the smallest possible value.
Traverse every starting index i from 0 to
n - k, calculatecurrentSum = prefixSum[i + k] - prefixSum[i], and calculatecurrentAverage = currentSum / k.Update maxAverage for every valid subarray and return maxAverage after complete traversal.
Dry Run
Maximum Average Subarray I Better Appraoch Dry Run.png
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: // Finds the maximum average using prefix sums. double findMaxAverage(vector<int>& nums, int k) { int n = nums.size(); // A valid subarray of size k cannot be formed. if (k <= 0 || n < k) { return 0.0; } vector<long long> prefixSum(n + 1, 0); // Store the sum of the first i elements at each position. for (int i = 0; i < n; i++) { prefixSum[i + 1] = prefixSum[i] + nums[i]; } double maxAverage = -DBL_MAX; // Calculate every size-k subarray sum in constant time. for (int i = 0; i <= n - k; i++) { long long currentSum = prefixSum[i + k] - prefixSum[i]; double currentAverage = static_cast<double>(currentSum) / k; // Keep the largest average found so far. if (currentAverage > maxAverage) { maxAverage = currentAverage; } } return maxAverage; }};int main() { vector<int> nums = {1, 12, -5, -6, 50, 3}; int k = 4; Solution solution; cout << fixed << setprecision(5) << solution.findMaxAverage(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N), where N is the size of the array. The prefix sum array is built once, and every subarray sum of size k is calculated in constant time.
Space Complexity: O(N), because an extra prefix sum array of size n + 1 is used.
Optimal Approach
A fixed-size sliding window begins with the first k elements. Moving the window one position forward removes the leftmost element and adds one new element from the right.
Every window contains the same number of elements. Therefore, the window with the maximum sum also has the maximum average. Tracking sums avoids repeated division during traversal, and one final division produces the required result.
Algorithm
Store the array size in n and return 0.0 when
k <= 0orn < k.Initialize windowSum with 0 and add the first k elements to form the first valid window.
Initialize maxSum with windowSum because the first window provides the first valid candidate.
Traverse
ifromkton - 1, wherenums[i]is the new element entering the window andnums[i - k]is the leftmost element leaving the previous window.Update
windowSumby addingnums[i]and subtractingnums[i - k], then updatemaxSumwhenever the new window produces a larger sum.Return
maxSum / kusing floating-point division after processing every window.
Dry Run
Maximum Average Subarray I Optimal Appraoch Dry Run.png
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: // Finds the maximum average using a fixed-size sliding window. double findMaxAverage(vector<int>& nums, int k) { int n = nums.size(); // A valid subarray of size k cannot be formed. if (k <= 0 || n < k) { return 0.0; } long long windowSum = 0; // Build the first valid window of size k. for (int i = 0; i < k; i++) { windowSum += nums[i]; } long long maxSum = windowSum; // Slide the window by adding one value and removing one value. for (int i = k; i < n; i++) { windowSum += nums[i]; windowSum -= nums[i - k]; // Keep the largest window sum found so far. if (windowSum > maxSum) { maxSum = windowSum; } } return static_cast<double>(maxSum) / k; }};int main() { vector<int> nums = {1, 12, -5, -6, 50, 3}; int k = 4; Solution solution; cout << fixed << setprecision(5) << solution.findMaxAverage(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N), where N represents the array size. Initial window construction processes K elements, while the remaining traversal processes every later element once.
Space Complexity: O(1), because only windowSum, maxSum, and loop variables require auxiliary storage.
FAQS
Q1. Why does invalid k return 0.0?
A non-positive k cannot represent a valid subarray length, while k > N cannot fit inside the array. The supplied problem contract uses 0.0 for both cases.
Q2. Why does the prefix sum array contain N + 1 positions?
The leading zero allows subarrays starting at index 0 to use the same subtraction formula as every other subarray.
Q3. Why does the Optimal Approach track maximum sum instead of maximum average?
Every candidate contains exactly K elements. Division by the same positive value preserves the ordering of all window sums.
Q4. Why is nums[i - k] subtracted during window movement?
Index i - k identifies the outgoing leftmost element from the previous window. Subtracting it keeps exactly K elements in the current window.
Q5. Does the solution support negative numbers?
Yes. Initializing the maximum from the first valid window prevents an incorrect default answer of 0 when every valid average is negative.
Q6. What happens if we calculate the average for every window instead of tracking its sum?
The result remains correct because every window contains exactly K elements. However, calculating the average repeatedly performs unnecessary floating-point division. Tracking sums and dividing only once at the end gives the same answer more simply.
Be the first to add a comment.