Maximum Average Subarray II
HardUpdated: Aug 2, 2025
Practice on:
Problem
You are given an integer array nums consisting of n elements, and an integer k.
Find a contiguous subarray whose length is greater than or equal to k
that has the maximum average value and return this value. Any answer with a calculation error less than 10-5 will be accepted.
Examples
Example 1:
Input: nums = [1,12,-5,-6,50,3], k = 4
Output: 12.75000
Explanation: - When the length is 4, averages are [0.5, 12.75, 10.5] and the maximum average is 12.75
- When the length is 5, averages are [10.4, 10.8] and the maximum average is 10.8
- When the length is 6, averages are [9.16667] and the maximum average is 9.16667
The maximum average is when we choose a subarray of length 4 (i.e., the sub array [12, -5, -6, 50]) which has the max average 12.75, so we return 12.75
Note that we do not consider the subarrays of length < 4.
Example 2:
Input: nums = [5], k = 1
Output: 5.00000
Constraints:
n == nums.length1 <= k <= n <= 10^4-10^4 <= nums[i] <= 10^4
Solution
Method 1 – Binary Search + Prefix Sum
Intuition
To find the maximum average subarray of length at least k, we can use binary search on the answer. For a candidate average, we check if there exists a subarray of length at least k whose average is at least that value. This can be checked using prefix sums and maintaining the minimum prefix sum for the window.
Approach
- Set left and right bounds for binary search as the min and max of nums.
- While right - left > 1e-5:
- Set mid = (left + right) / 2.
- Check if there exists a subarray of length at least k with average >= mid:
- Subtract mid from each element and compute prefix sums.
- For each i >= k, check if prefix[i] - min(prefix[0..i-k]) >= 0.
- If possible, set left = mid; else, set right = mid.
- Return left as the answer.
Code
C++
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k) {
double l = *min_element(nums.begin(), nums.end()), r = *max_element(nums.begin(), nums.end());
while (r - l > 1e-5) {
double m = (l + r) / 2;
vector<double> s(nums.size()+1);
for (int i = 0; i < nums.size(); ++i) s[i+1] = s[i] + nums[i] - m;
double min_pre = 0, ok = 0;
for (int i = k; i <= nums.size(); ++i) {
if (s[i] - min_pre >= 0) ok = 1;
min_pre = min(min_pre, s[i-k+1]);
}
if (ok) l = m; else r = m;
}
return l;
}
};
Go
func findMaxAverage(nums []int, k int) float64 {
l, r := float64(nums[0]), float64(nums[0])
for _, x := range nums {
if float64(x) < l { l = float64(x) }
if float64(x) > r { r = float64(x) }
}
for r-l > 1e-5 {
m := (l + r) / 2
s := make([]float64, len(nums)+1)
for i := 0; i < len(nums); i++ {
s[i+1] = s[i] + float64(nums[i]) - m
}
minPre, ok := 0.0, false
for i := k; i <= len(nums); i++ {
if s[i]-minPre >= 0 {
ok = true
}
if s[i-k+1] < minPre {
minPre = s[i-k+1]
}
}
if ok {
l = m
} else {
r = m
}
}
return l
}
Java
class Solution {
public double findMaxAverage(int[] nums, int k) {
double l = Arrays.stream(nums).min().getAsInt(), r = Arrays.stream(nums).max().getAsInt();
while (r - l > 1e-5) {
double m = (l + r) / 2;
double[] s = new double[nums.length+1];
for (int i = 0; i < nums.length; ++i) s[i+1] = s[i] + nums[i] - m;
double minPre = 0;
boolean ok = false;
for (int i = k; i <= nums.length; ++i) {
if (s[i] - minPre >= 0) ok = true;
minPre = Math.min(minPre, s[i-k+1]);
}
if (ok) l = m; else r = m;
}
return l;
}
}
Kotlin
class Solution {
fun findMaxAverage(nums: IntArray, k: Int): Double {
var l = nums.minOrNull()!!.toDouble()
var r = nums.maxOrNull()!!.toDouble()
while (r - l > 1e-5) {
val m = (l + r) / 2
val s = DoubleArray(nums.size+1)
for (i in nums.indices) s[i+1] = s[i] + nums[i] - m
var minPre = 0.0
var ok = false
for (i in k..nums.size) {
if (s[i] - minPre >= 0) ok = true
minPre = minOf(minPre, s[i-k+1])
}
if (ok) l = m else r = m
}
return l
}
}
Python
class Solution:
def findMaxAverage(self, nums: list[int], k: int) -> float:
l, r = min(nums), max(nums)
while r - l > 1e-5:
m = (l + r) / 2
s = [0]
for x in nums:
s.append(s[-1] + x - m)
min_pre = 0
ok = False
for i in range(k, len(nums)+1):
if s[i] - min_pre >= 0:
ok = True
min_pre = min(min_pre, s[i-k+1])
if ok:
l = m
else:
r = m
return l
Rust
impl Solution {
pub fn find_max_average(nums: Vec<i32>, k: i32) -> f64 {
let (mut l, mut r) = (*nums.iter().min().unwrap() as f64, *nums.iter().max().unwrap() as f64);
while r - l > 1e-5 {
let m = (l + r) / 2.0;
let mut s = vec![0.0; nums.len()+1];
for i in 0..nums.len() {
s[i+1] = s[i] + nums[i] as f64 - m;
}
let mut min_pre = 0.0;
let mut ok = false;
for i in k as usize..=nums.len() {
if s[i] - min_pre >= 0.0 {
ok = true;
}
min_pre = min_pre.min(s[i-k as usize+1]);
}
if ok {
l = m;
} else {
r = m;
}
}
l
}
}
TypeScript
class Solution {
findMaxAverage(nums: number[], k: number): number {
let l = Math.min(...nums), r = Math.max(...nums);
while (r - l > 1e-5) {
const m = (l + r) / 2;
const s = [0];
for (const x of nums) s.push(s[s.length-1] + x - m);
let minPre = 0, ok = false;
for (let i = k; i <= nums.length; ++i) {
if (s[i] - minPre >= 0) ok = true;
minPre = Math.min(minPre, s[i-k+1]);
}
if (ok) l = m; else r = m;
}
return l;
}
}
Complexity
- ⏰ Time complexity:
O(n log W), where W is the range of values in nums, due to binary search and prefix sum check. - 🧺 Space complexity:
O(n), for the prefix sum array.