Given an array arr[] and an integer k, find the maximum sum among all contiguous subarrays having a length greater than or equal to k.
Examples:
Input: arr[] = [1, -2, 2, -3], k = 3
Output: 1
Explanation: The sub-array of length at-least 3 that produces greatest sum is [1, -2, 2]Input: arr[] = [1, 1, 1, 1, 1, 1], k = 2
Output: 6
Explanation: The sub-array of length at-least 2 that produces greatest sum is [1, 1, 1, 1, 1, 1]Input: arr[] = [-4, -2, 1, -3], k = 2
Output: -1
Explanation: The sub-array of length at-least 2 that produces greatest sum is [-2, 1]
Table of Content
[Naive Approach] Checking All Possible Subarrays - O(n^2) Time and O(1) Space
The idea is to generate all possible subarrays starting from every index and keep adding elements to their sum. Whenever the current subarray length becomes k or more, update the maximum sum found so far.
Working of Approach:
- Start a subarray from each index and extend it one element at a time while maintaining its sum.
- Once the current subarray length is at least k, compare its sum with the current maximum and update the answer if needed.
- After checking all possible subarrays, return the maximum sum obtained.
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int maxSumWithK(vector<int> &arr, int k) {
int n = arr.size(), res = INT_MIN;
// Iterate over all possible starting points
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += arr[j];
// If size of current subarray is k
// or more
if (j - i + 1 >= k) res = max(res, sum);
}
}
return res;
}
int main() {
vector<int> arr = {1, 1, 1, 1, 1, 1};
int k = 2;
cout << maxSumWithK(arr, k) << endl;
return 0;
}
import java.util.*;
public class GFG {
public static int maxSumWithK(int[] arr, int k) {
int n = arr.length, res = Integer.MIN_VALUE;
// Iterate over all possible starting points
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += arr[j];
// If size of current subarray is k
// or more
if (j - i + 1 >= k) res = Math.max(res, sum);
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 1, 1, 1, 1, 1};
int k = 2;
System.out.println(maxSumWithK(arr, k));
}
}
def maxSumWithK(arr: list[int], k: int) -> int:
n = len(arr)
res = float('-inf')
# Iterate over all possible starting points
for i in range(n):
sum_ = 0
for j in range(i, n):
sum_ += arr[j]
# If size of current subarray is k
# or more
if j - i + 1 >= k:
res = max(res, sum_)
return res
if __name__ == "__main__":
arr = [1, 1, 1, 1, 1, 1]
k = 2
print(maxSumWithK(arr, k))
using System;
using System.Linq;
class GFG {
static int maxSumWithK(int[] arr, int k) {
int n = arr.Length, res = int.MinValue;
// Iterate over all possible starting points
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += arr[j];
// If size of current subarray is k
// or more
if (j - i + 1 >= k) res = Math.Max(res, sum);
}
}
return res;
}
static void Main() {
int[] arr = {1, 1, 1, 1, 1, 1};
int k = 2;
Console.WriteLine(maxSumWithK(arr, k));
}
}
function maxSumWithK(arr, k)
{
let n = arr.length, res = Number.NEGATIVE_INFINITY;
// Iterate over all possible starting points
for (let i = 0; i < n; i++) {
let sum = 0;
for (let j = i; j < n; j++) {
sum += arr[j];
// If size of current subarray is k
// or more
if (j - i + 1 >= k)
res = Math.max(res, sum);
}
}
return res;
}
// Driver Code
let arr = [1, 1, 1, 1, 1, 1];
let k = 2;
console.log(maxSumWithK(arr, k));
Output
6
[Better Approach] Kadane's Algorithm with Sliding Window - O(n) Time and O(n) Space
The idea is to use Kadane's algorithm to precompute the maximum subarray sum ending at each index and combine it with a sliding window of size k to efficiently find the maximum sum of a subarray having at least k elements.
Working of Approach:
- Use Kadane's algorithm to precompute the maximum subarray sum ending at every index.
- Compute the sum of each subarray of size k using a sliding window.
- For every window, either use only the window sum or extend it with the maximum subarray ending at index i - k to maximize the overall sum.
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int maxSumWithK(vector<int>& arr, int k) {
int n = arr.size();
// maxSum[i] stores the maximum subarray sum
// ending at index i
vector<int> maxSum(n);
maxSum[0] = arr[0];
// Use Kadane's algorithm to fill maxSum[]
int currMax = arr[0];
for (int i = 1; i < n; i++) {
currMax = max(arr[i], currMax + arr[i]);
maxSum[i] = currMax;
}
// Sum of first k elements
int sum = 0;
for (int i = 0; i < k; i++) {
sum += arr[i];
}
// Use sliding window concept
int res = sum;
for (int i = k; i < n; i++) {
// Compute sum of k elements ending with a[i]
sum = sum + arr[i] - arr[i-k];
// Update result if required
res = max(res, sum);
// Extend the current window with the maximum
// subarray ending at index i-k
res = max(res, sum + maxSum[i-k]);
}
return res;
}
int main() {
vector<int> arr = {1, 1, 1, 1, 1, 1};
int k = 2;
cout << maxSumWithK(arr, k);
return 0;
}
import java.util.*;
class GFG {
static int maxSumWithK(int[] arr, int k) {
int n = arr.length;
// maxSum[i] stores the maximum subarray sum
// ending at index i
int[] maxSum = new int[n];
maxSum[0] = arr[0];
// Use Kadane's algorithm to fill maxSum[]
int currMax = arr[0];
for (int i = 1; i < n; i++) {
currMax = Math.max(arr[i], currMax + arr[i]);
maxSum[i] = currMax;
}
// Sum of first k elements
int sum = 0;
for (int i = 0; i < k; i++) {
sum += arr[i];
}
// Use sliding window concept
int res = sum;
for (int i = k; i < n; i++) {
// Compute sum of k elements ending with arr[i]
sum = sum + arr[i] - arr[i - k];
// Update result if required
res = Math.max(res, sum);
// Extend the current window with the maximum
// subarray ending at index i-k
res = Math.max(res, sum + maxSum[i - k]);
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 1, 1, 1, 1, 1};
int k = 2;
System.out.println(maxSumWithK(arr, k));
}
}
def maxSumWithK(arr: list[int], k: int) -> int:
n = len(arr)
# maxSum[i] stores the maximum subarray sum
# ending at index i
maxSum = [0] * n
maxSum[0] = arr[0]
# Use Kadane's algorithm to fill maxSum[]
currMax = arr[0]
for i in range(1, n):
currMax = max(arr[i], currMax + arr[i])
maxSum[i] = currMax
# Sum of first k elements
sum = 0
for i in range(k):
sum += arr[i]
# Use sliding window concept
res = sum
for i in range(k, n):
# Compute sum of k elements ending with arr[i]
sum = sum + arr[i] - arr[i - k]
# Update result if required
res = max(res, sum)
# Extend the current window with the maximum
# subarray ending at index i-k
res = max(res, sum + maxSum[i - k])
return res
if __name__ == "__main__":
arr = [1, 1, 1, 1, 1, 1]
k = 2
print(maxSumWithK(arr, k))
using System;
class GFG {
static int maxSumWithK(int[] arr, int k) {
int n = arr.Length;
// maxSum[i] stores the maximum subarray sum
// ending at index i
int[] maxSum = new int[n];
maxSum[0] = arr[0];
// Use Kadane's algorithm to fill maxSum[]
int currMax = arr[0];
for (int i = 1; i < n; i++) {
currMax = Math.Max(arr[i], currMax + arr[i]);
maxSum[i] = currMax;
}
// Sum of first k elements
int sum = 0;
for (int i = 0; i < k; i++) {
sum += arr[i];
}
// Use sliding window concept
int res = sum;
for (int i = k; i < n; i++) {
// Compute sum of k elements ending with arr[i]
sum = sum + arr[i] - arr[i - k];
// Update result if required
res = Math.Max(res, sum);
// Extend the current window with the maximum
// subarray ending at index i-k
res = Math.Max(res, sum + maxSum[i - k]);
}
return res;
}
static void Main() {
int[] arr = {1, 1, 1, 1, 1, 1};
int k = 2;
Console.WriteLine(maxSumWithK(arr, k));
}
}
function maxSumWithK(arr, k)
{
let n = arr.length;
// maxSum[i] stores the maximum subarray sum
// ending at index i
let maxSum = new Array(n);
maxSum[0] = arr[0];
// Use Kadane's algorithm to fill maxSum[]
let currMax = arr[0];
for (let i = 1; i < n; i++) {
currMax = Math.max(arr[i], currMax + arr[i]);
maxSum[i] = currMax;
}
// Sum of first k elements
let sum = 0;
for (let i = 0; i < k; i++) {
sum += arr[i];
}
// Use sliding window concept
let res = sum;
for (let i = k; i < n; i++) {
// Compute sum of k elements ending with arr[i]
sum = sum + arr[i] - arr[i - k];
// Update result if required
res = Math.max(res, sum);
// Extend the current window with the maximum
// subarray ending at index i-k
res = Math.max(res, sum + maxSum[i - k]);
}
return res;
}
// Driver Code
let arr = [1, 1, 1, 1, 1, 1];
let k = 2;
console.log(maxSumWithK(arr, k));
Output
6
[Expected Approach] Sliding Window with Kadane's Optimization - O(n) Time and O(1) Space
The idea is to use a sliding window of size k and apply Kadane's optimization by maintaining the sum of the current window along with an accumulated prefix before the window. Whenever the accumulated prefix becomes negative, discard it since removing a negative prefix increases the overall subarray sum.
Working of Approach:
- Compute the sum of the first k elements and slide the window one element at a time.
- Keep track of the sum of elements before the current window using last.
- Whenever last becomes negative, remove it from the current sum, as discarding a negative prefix increases the overall subarray sum.
Let us understand with an example:
- Consider arr[] = {1, 1, 1, 1, 1, 1} and k = 2. The initial window sum is 2, so maxSum = 2, last = 0, and j = 0.
- Move the window to include the next element. Extend the current window by adding the next element and accumulate the removed elements in last.
- Since all elements are positive, last never becomes negative, so no prefix is removed and the current sum keeps increasing.
- At each step, compare the current sum with maxSum and update it whenever a larger value is found.
- After processing the entire array, the maximum subarray sum having at least k elements is 6.
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int maxSumWithK(vector<int> &arr, int k)
{
// Calculate initial sum of
// first k elements (first window)
int sum = 0;
for (int i = 0; i < k; i++)
{
sum += arr[i];
}
int last = 0;
int j = 0;
int maxSum = INT_MIN;
maxSum = max(maxSum, sum);
// Process rest of the array after first k elements
for (int i = k; i < arr.size(); i++)
{
// Add current element to window sum
sum = sum + arr[i];
// Add element at j to the accumulated prefix
last = last + arr[j++];
// Update maxSum if current window sum is greater
maxSum = max(maxSum, sum);
// Remove the accumulated negative prefix
// if it increases the overall subarray sum
if (last < 0)
{
sum = sum - last;
maxSum = max(maxSum, sum);
last = 0;
}
}
return maxSum;
}
int main()
{
vector<int> arr = {1, 1, 1, 1, 1, 1};
int k = 2;
cout << maxSumWithK(arr, k);
return 0;
}
import java.util.Arrays;
public class GFG {
public static int maxSumWithK(int[] arr, int k)
{
// Calculate initial sum of
// first k elements (first window)
int sum = 0;
for (int i = 0; i < k; i++) {
sum += arr[i];
}
int last = 0;
int j = 0;
int maxSum = Integer.MIN_VALUE;
maxSum = Math.max(maxSum, sum);
// Process rest of the array after first k elements
for (int i = k; i < arr.length; i++) {
// Add current element to window sum
sum = sum + arr[i];
// Add element at j to the accumulated prefix
last = last + arr[j++];
// Update maxSum if current window sum is greater
maxSum = Math.max(maxSum, sum);
// Remove the accumulated negative prefix
// if it increases the overall subarray sum
if (last < 0) {
sum = sum - last;
maxSum = Math.max(maxSum, sum);
last = 0;
}
}
return maxSum;
}
public static void main(String[] args)
{
int[] arr = {1, 1, 1, 1, 1, 1};
int k = 2;
System.out.println(maxSumWithK(arr, k));
}
}
def maxSumWithK(arr: list[int], k: int) -> int:
# Calculate initial sum of
# first k elements (first window)
sum = 0
for i in range(k):
sum += arr[i]
last = 0
j = 0
maxSum = float('-inf')
maxSum = max(maxSum, sum)
# Process rest of the array after first k elements
for i in range(k, len(arr)):
# Add current element to window sum
sum = sum + arr[i]
# Add element at j to the accumulated prefix
last = last + arr[j]
j += 1
# Update maxSum if current window sum is greater
maxSum = max(maxSum, sum)
# Remove the accumulated negative prefix
# if it increases the overall subarray sum
if last < 0:
sum = sum - last
maxSum = max(maxSum, sum)
last = 0
return maxSum
if __name__ == "__main__":
arr = [1, 1, 1, 1, 1, 1]
k = 2
print(maxSumWithK(arr, k))
using System;
public class GFG {
public static int maxSumWithK(int[] arr, int k)
{
// Calculate initial sum of
// first k elements (first window)
int sum = 0;
for (int i = 0; i < k; i++) {
sum += arr[i];
}
int last = 0;
int j = 0;
int maxSum = int.MinValue;
maxSum = Math.Max(maxSum, sum);
// Process rest of the array after first k elements
for (int i = k; i < arr.Length; i++) {
// Add current element to window sum
sum = sum + arr[i];
// Add element at j to the accumulated prefix
last = last + arr[j++];
// Update maxSum if current window sum is greater
maxSum = Math.Max(maxSum, sum);
// Remove the accumulated negative prefix
// if it increases the overall subarray sum
if (last < 0) {
sum = sum - last;
maxSum = Math.Max(maxSum, sum);
last = 0;
}
}
return maxSum;
}
public static void Main()
{
int[] arr = {1, 1, 1, 1, 1, 1};
int k = 2;
Console.WriteLine(maxSumWithK(arr, k));
}
}
function maxSumWithK(arr, k)
{
// Calculate initial sum of
// first k elements (first window)
let sum = 0;
for (let i = 0; i < k; i++) {
sum += arr[i];
}
let last = 0;
let j = 0;
let maxSum = Number.NEGATIVE_INFINITY;
maxSum = Math.max(maxSum, sum);
// Process rest of the array after first k elements
for (let i = k; i < arr.length; i++) {
// Add current element to window sum
sum = sum + arr[i];
// Add element at j to the accumulated prefix
last = last + arr[j++];
// Update maxSum if current window sum is greater
maxSum = Math.max(maxSum, sum);
// Remove the accumulated negative prefix
// if it increases the overall subarray sum
if (last < 0) {
sum = sum - last;
maxSum = Math.max(maxSum, sum);
last = 0;
}
}
return maxSum;
}
// Driver Code
const arr = [1, 1, 1, 1, 1, 1];
const k = 2;
console.log(maxSumWithK(arr, k));
Output
6