Given an integer array arr[] and an integer x. The task is to find the maximum length of contiguous subarray such that the average of its elements is greater than or equal to x.
Examples:
Input: arr[] = [-2, 1, 6, -3], x = 3
Output: 2
Explanation: Subarray [1, 6] has average 3.5 which is greater than 3Input: arr[] = [2, -3, 3, 2, 1], x = 2
Output: 3
Explanation: Subarray [3, 2, 1] has average 2 which is equal to 2Input: arr[] = [5, 4, -1, 2, 3], x = 3
Output: 2
Explanation: Subarray [5, 4] has average 4.5 which is greater than 3
Table of Content
[Naive Approach] Check for all Subarrays - O(n^2) Time and O(1) Space
The idea is to examine all possible subarrays and compute their sum and length. Instead of directly comparing the average using division, we use the equivalent condition sum ≥ length × x, which avoids floating-point errors. This is derived from the observation that sum / length ≥ x implies sum ≥ length × x, since length is always positive. Using this integer-based check, we update the maximum subarray length whenever the condition is satisfied.
// C++ Code to find longest subarray with average
// >= x using Naive Approach
#include <iostream>
#include <vector>
using namespace std;
int maxLengthSubarrayAvg(vector<int> &arr, int x) {
int n = arr.size();
int maxLen = 0;
// Traverse all possible subarrays
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
// Add current element to sum
sum += arr[j];
int len = j - i + 1;
// Check if average >= x
if (sum >= len * x) {
maxLen = max(maxLen, len);
}
}
}
return maxLen;
}
int main() {
vector<int> arr = {-2, 1, 6, -3};
int x = 3;
cout << maxLengthSubarrayAvg(arr, x);
return 0;
}
// Java Code to find longest subarray with average
// >= x using Naive Approach
class GfG {
static int maxLengthSubarrayAvg(int[] arr, int x) {
int n = arr.length;
int maxLen = 0;
// Traverse all possible subarrays
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
// Add current element to sum
sum += arr[j];
int len = j - i + 1;
// Check if average >= x
if (sum >= len * x) {
maxLen = Math.max(maxLen, len);
}
}
}
return maxLen;
}
public static void main(String[] args) {
int[] arr = {-2, 1, 6, -3};
int x = 3;
System.out.println(maxLengthSubarrayAvg(arr, x));
}
}
# Python Code to find longest subarray with average
# >= x using Naive Approach
def maxLengthSubarrayAvg(arr, x):
n = len(arr)
maxLen = 0
# Traverse all possible subarrays
for i in range(n):
sum = 0
for j in range(i, n):
# Add current element to sum
sum += arr[j]
length = j - i + 1
# Check if average >= x
if sum >= length * x:
maxLen = max(maxLen, length)
return maxLen
if __name__ == "__main__":
arr = [-2, 1, 6, -3]
x = 3
print(maxLengthSubarrayAvg(arr, x))
// C# Code to find longest subarray with average
// >= x using Naive Approach
using System;
class GfG {
static int maxLengthSubarrayAvg(int[] arr, int x) {
int n = arr.Length;
int maxLen = 0;
// Traverse all possible subarrays
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
// Add current element to sum
sum += arr[j];
int len = j - i + 1;
// Check if average >= x
if (sum >= len * x) {
maxLen = Math.Max(maxLen, len);
}
}
}
return maxLen;
}
static void Main(string[] args) {
int[] arr = {-2, 1, 6, -3};
int x = 3;
Console.WriteLine(maxLengthSubarrayAvg(arr, x));
}
}
// JavaScript Code to find longest subarray with average
// >= x using Naive Approach
function maxLengthSubarrayAvg(arr, x) {
let n = arr.length;
let maxLen = 0;
// Traverse all possible subarrays
for (let i = 0; i < n; i++) {
let sum = 0;
for (let j = i; j < n; j++) {
// Add current element to sum
sum += arr[j];
let len = j - i + 1;
// Check if average >= x
if (sum >= len * x) {
maxLen = Math.max(maxLen, len);
}
}
}
return maxLen;
}
// Driver Code
let arr = [-2, 1, 6, -3];
let x = 3;
console.log(maxLengthSubarrayAvg(arr, x));
Output
2
[Expected Approach] Using Binary Search + Prefix Sum - O(n*log(n)) Time and O(n) Space
The idea is to use Binary Search and Prefix Sum to solve this problem efficiently. Let the required Longest subarray be arr[i..j] and its length is l = j - i + 1. The given condition: (Σ arr[i..j]) / l ≥ x
Rewriting it:
(Σ arr[i..j] - x * l) / l ≥ 0 ...(1)Equation (1) implies that subtracting
xfrom each element in the subarray and then computing the average should yield a non-negative value. So, define a new arrayarr1wherearr1[i] = arr[i] - x. This transforms the condition into:
Σ arr1[i..j] / l ≥ 0
=> Σ arr1[i..j] ≥ 0 ...(2)Thus, the task reduces to finding the longest subarray with sum ≥ 0 in the transformed array
arr1. The Longest subarray having sum greater than or equal to zero can be found by method discussed in following article: Longest subarray having sum greater than k.
Steps to implement the above idea:
- Subtract x from every element in the array to transform the average condition into a sum condition.
- Initialize and build a 2D array preSum to store prefix sums along with their indices.
- Sort preSum based on sum values and for ties, by their indices using a custom comparator.
- Construct minInd array to store minimum index seen so far in sorted preSum for binary search use.
- Recalculate prefix sum from start and check for each position if prefix sum ≥ 0, update maxLen.
- If prefix sum is negative, binary search in preSum to find largest prefix ≤ current sum.
- If such prefix is found and its index is less than current, update maxLen with valid subarray length.
- Finally, return maxLen as the length of the longest subarray with average ≥ x.
// C++ Code to find longest subarray with average
// >= x using Binary Search + Prefix Sum
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Comparator function to sort preSum
bool comparePrefix(vector<int> &a,
vector<int> &b) {
// If prefix sums are equal, compare by index
if (a[0] == b[0]) {
return a[1] < b[1];
}
// Otherwise compare by prefix sum value
return a[0] < b[0];
}
int maxLengthSubarrayAvg(vector<int> &arr, int x) {
int n = arr.size();
// Subtract x from each element so that
// we can convert the average condition to
// a sum condition.
for (int i = 0; i < n; i++) {
arr[i] -= x;
}
int maxLen = 0;
vector<vector<int>> preSum;
int sum = 0;
// Array to store minimum index
// seen so far in sorted prefix
vector<int> minInd(n);
// Compute prefix sums and store with index
for (int i = 0; i < n; i++) {
sum += arr[i];
preSum.push_back({sum, i});
}
// Sort preSum using regular function
sort(preSum.begin(), preSum.end(), comparePrefix);
minInd[0] = preSum[0][1];
for (int i = 1; i < n; i++) {
minInd[i] = min(minInd[i - 1], preSum[i][1]);
}
sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
// If prefix sum is non-negative, then subarray [0..i]
// satisfies the average condition, update maxLen
if (sum >= 0) {
maxLen = max(maxLen, i + 1);
}
else {
// Binary search in preSum to find the largest
// index such that prefix sum ≤ current sum
int l = 0, r = n - 1, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (preSum[mid][0] <= sum) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
// If such prefix exists and its index is < i,
// then subarray (minInd[ans]+1 to i) satisfies
// the average condition
if (ans != -1 && minInd[ans] < i) {
maxLen = max(maxLen, i - minInd[ans]);
}
}
}
return maxLen;
}
int main() {
vector<int> arr = {-2, 1, 6, -3};
int x = 3;
cout << maxLengthSubarrayAvg(arr, x);
return 0;
}
// Java Code to find longest subarray with average
// >= x using Binary Search + Prefix Sum
import java.util.*;
class GfG {
// Comparator function to sort preSum
static boolean comparePrefix(int[] a, int[] b) {
// If prefix sums are equal, compare by index
if (a[0] == b[0]) {
return a[1] < b[1];
}
// Otherwise compare by prefix sum value
return a[0] < b[0];
}
static int maxLengthSubarrayAvg(int[] arr, int x) {
int n = arr.length;
// Subtract x from each element so that
// we can convert the average condition to
// a sum condition.
for (int i = 0; i < n; i++) {
arr[i] -= x;
}
int maxLen = 0;
List<int[]> preSum = new ArrayList<>();
int sum = 0;
// Array to store minimum index
// seen so far in sorted prefix
int[] minInd = new int[n];
// Compute prefix sums and store with index
for (int i = 0; i < n; i++) {
sum += arr[i];
preSum.add(new int[]{sum, i});
}
// Sort preSum using regular function
Collections.sort(preSum, new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
if (a[0] == b[0]) {
return Integer.compare(a[1], b[1]);
}
return Integer.compare(a[0], b[0]);
}
});
minInd[0] = preSum.get(0)[1];
for (int i = 1; i < n; i++) {
minInd[i] = Math.min(minInd[i - 1], preSum.get(i)[1]);
}
sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
// If prefix sum is non-negative, then subarray [0..i]
// satisfies the average condition, update maxLen
if (sum >= 0) {
maxLen = Math.max(maxLen, i + 1);
}
else {
// Binary search in preSum to find the largest
// index such that prefix sum ≤ current sum
int l = 0, r = n - 1, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (preSum.get(mid)[0] <= sum) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
// If such prefix exists and its index is < i,
// then subarray (minInd[ans]+1 to i) satisfies
// the average condition
if (ans != -1 && minInd[ans] < i) {
maxLen = Math.max(maxLen, i - minInd[ans]);
}
}
}
return maxLen;
}
public static void main(String[] args) {
int[] arr = {-2, 1, 6, -3};
int x = 3;
System.out.println(maxLengthSubarrayAvg(arr, x));
}
}
# Python Code to find longest subarray with average
# >= x using Binary Search + Prefix Sum
def comparePrefix(a, b):
# If prefix sums are equal, compare by index
if a[0] == b[0]:
return a[1] - b[1]
# Otherwise compare by prefix sum value
return a[0] - b[0]
def maxLengthSubarrayAvg(arr, x):
n = len(arr)
# Subtract x from each element so that
# we can convert the average condition to
# a sum condition.
for i in range(n):
arr[i] -= x
maxLen = 0
preSum = []
sum = 0
# Array to store minimum index
# seen so far in sorted prefix
minInd = [0]*n
# Compute prefix sums and store with index
for i in range(n):
sum += arr[i]
preSum.append([sum, i])
# Sort preSum using regular function
preSum.sort(key=lambda pair: (pair[0], pair[1]))
minInd[0] = preSum[0][1]
for i in range(1, n):
minInd[i] = min(minInd[i - 1], preSum[i][1])
sum = 0
for i in range(n):
sum += arr[i]
# If prefix sum is non-negative, then subarray [0..i]
# satisfies the average condition, update maxLen
if sum >= 0:
maxLen = max(maxLen, i + 1)
else:
# Binary search in preSum to find the largest
# index such that prefix sum ≤ current sum
l, r, ans = 0, n - 1, -1
while l <= r:
mid = (l + r) // 2
if preSum[mid][0] <= sum:
ans = mid
l = mid + 1
else:
r = mid - 1
# If such prefix exists and its index is < i,
# then subarray (minInd[ans]+1 to i) satisfies
# the average condition
if ans != -1 and minInd[ans] < i:
maxLen = max(maxLen, i - minInd[ans])
return maxLen
if __name__ == "__main__":
arr = [-2, 1, 6, -3]
x = 3
print(maxLengthSubarrayAvg(arr, x))
// C# Code to find longest subarray with average
// >= x using Binary Search + Prefix Sum
using System;
using System.Collections.Generic;
class GfG {
// Comparator function to sort preSum
static bool comparePrefix(List<int> a,
List<int> b) {
// If prefix sums are equal, compare by index
if (a[0] == b[0]) {
return a[1] < b[1];
}
// Otherwise compare by prefix sum value
return a[0] < b[0];
}
static int maxLengthSubarrayAvg(int[] arr, int x) {
int n = arr.Length;
// Subtract x from each element so that
// we can convert the average condition to
// a sum condition.
for (int i = 0; i < n; i++) {
arr[i] -= x;
}
int maxLen = 0;
List<List<int>> preSum = new List<List<int>>();
int sum = 0;
// Array to store minimum index
// seen so far in sorted prefix
int[] minInd = new int[n];
// Compute prefix sums and store with index
for (int i = 0; i < n; i++) {
sum += arr[i];
preSum.Add(new List<int> { sum, i });
}
// Sort preSum using regular function
preSum.Sort((a, b) => {
if (a[0] == b[0]) {
return a[1].CompareTo(b[1]);
}
return a[0].CompareTo(b[0]);
});
minInd[0] = preSum[0][1];
for (int i = 1; i < n; i++) {
minInd[i] = Math.Min(minInd[i - 1], preSum[i][1]);
}
sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
// If prefix sum is non-negative, then subarray [0..i]
// satisfies the average condition, update maxLen
if (sum >= 0) {
maxLen = Math.Max(maxLen, i + 1);
}
else {
// Binary search in preSum to find the largest
// index such that prefix sum ≤ current sum
int l = 0, r = n - 1, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (preSum[mid][0] <= sum) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
// If such prefix exists and its index is < i,
// then subarray (minInd[ans]+1 to i) satisfies
// the average condition
if (ans != -1 && minInd[ans] < i) {
maxLen = Math.Max(maxLen, i - minInd[ans]);
}
}
}
return maxLen;
}
static void Main() {
int[] arr = { -2, 1, 6, -3 };
int x = 3;
Console.WriteLine(maxLengthSubarrayAvg(arr, x));
}
}
// JavaScript Code to find longest subarray with average
// >= x using Binary Search + Prefix Sum
function comparePrefix(a, b) {
// If prefix sums are equal, compare by index
if (a[0] === b[0]) {
return a[1] - b[1];
}
// Otherwise compare by prefix sum value
return a[0] - b[0];
}
function maxLengthSubarrayAvg(arr, x) {
let n = arr.length;
// Subtract x from each element so that
// we can convert the average condition to
// a sum condition.
for (let i = 0; i < n; i++) {
arr[i] -= x;
}
let maxLen = 0;
let preSum = [];
let sum = 0;
// Array to store minimum index
// seen so far in sorted prefix
let minInd = Array(n);
// Compute prefix sums and store with index
for (let i = 0; i < n; i++) {
sum += arr[i];
preSum.push([sum, i]);
}
// Sort preSum using regular function
preSum.sort(comparePrefix);
minInd[0] = preSum[0][1];
for (let i = 1; i < n; i++) {
minInd[i] = Math.min(minInd[i - 1], preSum[i][1]);
}
sum = 0;
for (let i = 0; i < n; i++) {
sum += arr[i];
// If prefix sum is non-negative, then subarray [0..i]
// satisfies the average condition, update maxLen
if (sum >= 0) {
maxLen = Math.max(maxLen, i + 1);
}
else {
// Binary search in preSum to find the largest
// index such that prefix sum ≤ current sum
let l = 0, r = n - 1, ans = -1;
while (l <= r) {
let mid = Math.floor((l + r) / 2);
if (preSum[mid][0] <= sum) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
// If such prefix exists and its index is < i,
// then subarray (minInd[ans]+1 to i) satisfies
// the average condition
if (ans !== -1 && minInd[ans] < i) {
maxLen = Math.max(maxLen, i - minInd[ans]);
}
}
}
return maxLen;
}
// Driver Code
let arr = [-2, 1, 6, -3];
let x = 3;
console.log(maxLengthSubarrayAvg(arr, x));
Output
2