Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Maximum sum of at most K non-overlapping Subarray

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

Given an array, arr[] of size N, the task is to find the sum of the at most K non-overlapping contiguous subarray within an arr[] with the maximum sum. 

Examples:

Input: arr[] = [4, 1, -3, 7, -5, 6, -2, 1], K = 3
Output: 18
Explanation: In the above input, the maximum k subarray sum is 18 and the subarrays are {{4, 1}, {7}, {6}}

Input: arr[] = [8, -1, 4, 2, 6, -6, 4, -1], K = 2
Output: 23
Explanation: In the above input, the maximum k subarray sum is 23 and the subarrays are {{8, -1, 4, 2, 6}, {4}}

Approach: This can be solved with the following idea:

Calculating the prefix sum will let us know about the previous maximum element. At, each point see whether to exclude the element or include the element.

Below are the steps involved in the implementation of the code:

  • Take an array pre_sum[] of size N + 1(N is the size of array arr[]).
  • Initialise pre_sum[0] = 0 and store prefix sum of array arr[] in pre_sum[] array from index 1 ≤ i ≤ N. 
  • Let i be the index we are at, j be the total transaction remaining, b represent if we want to start from this index(1 for buying and 0 for selling), and pre_sum[] represents the sum of the array.
  • Transitions:
    • dp[i][j][1] = max(-A[i] + dp[j][i + 1][0], dp[j][i + 1][1])
    • dp[i][j][0] = max(A[i] + dp[j – 1][i + 1][1], dp[j][i + 1][0])

Below is the Implementation of the above approach:

C++




// C++ program to find out the maximum
// sum of at most K non-overlapping
// subarray
#include <bits/stdc++.h>
using namespace std;
 
int B;
vector<int> pre_sum;
int dp[501][201][2];
int solve(int j, int i, int b)
{
 
    // If the result has already been
    // calculated return that result
    if (dp[i][j][b] != -1)
        return dp[i][j][b];
 
    // If i has reached the end of the
    // array return 0
    if (i == B)
        return 0;
 
    // If we have exhausted the number of
    // transaction return 0
    if (j == 0)
        return 0;
 
    int res;
    if (b == 1)
        res = max(-pre_sum[i] + solve(j, i + 1, 0),
                  solve(j, i + 1, 1));
 
    else
        res = max(pre_sum[i] + solve(j - 1, i + 1, 1),
                  solve(j, i + 1, 0));
 
    // Return the result
    return dp[i][j][b] = res;
}
 
int maxSum(int K, int N, int arr[])
{
    pre_sum = vector<int>(N + 1, 0);
 
    // Finding prefix sum of array arr[]
    for (int i = 1; i <= N; i++)
        pre_sum[i] = pre_sum[i - 1] + arr[i - 1];
 
    // Initializing DP with -1
    memset(dp, -1, sizeof(dp));
 
    // Copying n to global B
    B = N + 1;
 
    // Function to find maximum
    return solve(K, 0, 1);
}
 
// Driver code
int main()
{
 
    // Test case 1
    int arr1[] = { 4, 1, -3, 7, -5, 6, -2, 1 };
    int K1 = 3;
    int N1 = sizeof(arr1) / sizeof(arr1[0]);
 
    // Function call
    cout << maxSum(K1, N1, arr1) << endl;
 
    // Test case 2
    int arr2[] = { 8, -1, 4, 2, 6, -6, 4, -1 };
    int K2 = 2;
    int N2 = sizeof(arr2) / sizeof(arr2[0]);
 
    // Function call
    cout << maxSum(K2, N2, arr2);
    return 0;
}


Java




// Java program to find out the maximum
// sum of at most K non-overlapping
// subarray
import java.util.*;
 
class GFG {
  static int B;
  static int[][][] dp = new int[501][201][2];
  static List<Integer> pre_sum = new ArrayList<>();
 
  public static int solve(int j, int i, int b, int[] arr)
  {
 
    // If the result has already been
    // calculated return that result
    if (dp[i][j][b] != -1)
      return dp[i][j][b];
 
    // If i has reached the end of the
    // array return 0
    if (i == B)
      return 0;
 
    // If we have exhausted the number of
    // transaction return 0
    if (j == 0)
      return 0;
 
    int res;
    if (b == 1)
      res = Math.max(-pre_sum.get(i)
                     + solve(j, i + 1, 0, arr),
                     solve(j, i + 1, 1, arr));
    else
      res = Math.max(
      pre_sum.get(i)
      + solve(j - 1, i + 1, 1, arr),
      solve(j, i + 1, 0, arr));
 
    // Return the result
    return dp[i][j][b] = res;
  }
 
  public static int maxSum(int K, int N, int[] arr)
  {
    pre_sum = new ArrayList<>(
      Collections.nCopies(N + 1, 0));
 
    // Finding prefix sum of array arr[]
    for (int i = 1; i <= N; i++)
      pre_sum.set(i, pre_sum.get(i - 1) + arr[i - 1]);
 
    // Initializing DP with -1
    for (int[][] row : dp)
      for (int[] rowColumn : row)
        Arrays.fill(rowColumn, -1);
 
    // Copying n to global B
    B = N + 1;
 
    // Function to find maximum
    return solve(K, 0, 1, arr);
  }
 
  // Driver code
  public static void main(String[] args)
  {
 
    // Test case 1
    int[] arr1 = { 4, 1, -3, 7, -5, 6, -2, 1 };
    int K1 = 3;
    int N1 = arr1.length;
 
    // Function call
    System.out.println(maxSum(K1, N1, arr1));
 
    // Test case 2
    int[] arr2 = { 8, -1, 4, 2, 6, -6, 4, -1 };
    int K2 = 2;
    int N2 = arr2.length;
 
    // Function call
    System.out.println(maxSum(K2, N2, arr2));
  }
}
 
// This code is contributed by Prasad Kandekar(prasad264)


C#




using System;
using System.Collections.Generic;
 
public class GFG {
  static int B;
  static int[, , ] dp = new int[501, 201, 2];
  static List<int> pre_sum = new List<int>();
 
  public static int solve(int j, int i, int b, int[] arr)
  {
 
    // If the result has already been
    // calculated return that result
    if (dp[i, j, b] != -1)
      return dp[i, j, b];
 
    // If i has reached the end of the
    // array return 0
    if (i == B)
      return 0;
 
    // If we have exhausted the number of
    // transaction return 0
    if (j == 0)
      return 0;
 
    int res;
    if (b == 1)
      res = Math.Max(-pre_sum[i]
                     + solve(j, i + 1, 0, arr),
                     solve(j, i + 1, 1, arr));
    else
      res = Math.Max(
      pre_sum[i] + solve(j - 1, i + 1, 1, arr),
      solve(j, i + 1, 0, arr));
 
    // Return the result
    return dp[i, j, b] = res;
  }
 
  public static int maxSum(int K, int N, int[] arr)
  {
    for (int i = 0; i < N + 1; i++) {
      pre_sum.Add(0);
    }
 
    // Finding prefix sum of array arr[]
    for (int i = 1; i <= N; i++)
      pre_sum[i] = pre_sum[i - 1] + arr[i - 1];
 
    // Initializing DP with -1
    for (int i = 0; i < 501; i++) {
      for (int j = 0; j < 201; j++) {
        dp[i, j, 0] = dp[i, j, 1] = -1;
      }
    }
 
    // Copying n to global B
    B = N + 1;
 
    // Function to find maximum
    return solve(K, 0, 1, arr);
  }
 
  // Driver code
  static public void Main()
  {
 
    // Test case 1
    int[] arr1 = { 4, 1, -3, 7, -5, 6, -2, 1 };
    int K1 = 3;
    int N1 = arr1.Length;
 
    // Function call
    Console.WriteLine(maxSum(K1, N1, arr1));
 
    // Test case 2
    int[] arr2 = { 8, -1, 4, 2, 6, -6, 4, -1 };
    int K2 = 2;
    int N2 = arr2.Length;
 
    // Function call
    Console.WriteLine(maxSum(K2, N2, arr2));
  }
}
 
// This code is contributed by Rohit Pradhan


Python3




import math
 
B = 0
dp = [[[0 for _ in range(2)] for _ in range(201)] for _ in range(501)]
pre_sum = []
 
def solve(j, i, b, arr):
    global dp, pre_sum
 
    # If the result has already been calculated, return that result
    if dp[i][j][b] != 0:
        return dp[i][j][b]
 
    # If i has reached the end of the array, return 0
    if i == B:
        return 0
 
    # If we have exhausted the number of transactions, return 0
    if j == 0:
        return 0
 
    res = 0
    if b == 1:
        res = max(-pre_sum[i] + solve(j, i + 1, 0, arr), solve(j, i + 1, 1, arr))
    else:
        res = max(pre_sum[i] + solve(j - 1, i + 1, 1, arr), solve(j, i + 1, 0, arr))
 
    # Return the result
    dp[i][j][b] = res
    return res
 
def maxSum(K, N, arr):
    global B, dp, pre_sum
 
    pre_sum = [0] * (N + 1)
 
    # Finding prefix sum of array arr[]
    for i in range(1, N + 1):
        pre_sum[i] = pre_sum[i - 1] + arr[i - 1]
 
    # Initializing DP with 0
    dp = [[[0 for _ in range(2)] for _ in range(201)] for _ in range(501)]
 
    # Copying n to global B
    B = N + 1
 
    # Function to find maximum
    return solve(K, 0, 1, arr)
 
# Driver code
if __name__ == '__main__':
    # Test case 1
    arr1 = [4, 1, -3, 7, -5, 6, -2, 1]
    K1 = 3
    N1 = len(arr1)
 
    # Function call
    print(maxSum(K1, N1, arr1))
 
    # Test case 2
    arr2 = [8, -1, 4, 2, 6, -6, 4, -1]
    K2 = 2
    N2 = len(arr2)
 
    # Function call
    print(maxSum(K2, N2, arr2))


Javascript




let B;
let dp = Array.from(Array(501), () =>
Array.from(Array(201), () => new Array(2).fill(-1))
);
let pre_sum = [];
 
function solve(j, i, b, arr) {
// If the result has already been
// calculated return that result
if (dp[i][j][b] !== -1) return dp[i][j][b];
 
// If i has reached the end of the
// array return 0
if (i === B) return 0;
 
// If we have exhausted the number of
// transaction return 0
if (j === 0) return 0;
 
let res;
if (b === 1)
res = Math.max(
-pre_sum[i] + solve(j, i + 1, 0, arr),
solve(j, i + 1, 1, arr)
);
else
res = Math.max(
pre_sum[i] + solve(j - 1, i + 1, 1, arr),
solve(j, i + 1, 0, arr)
);
 
// Return the result
return (dp[i][j][b] = res);
}
 
function maxSum(K, N, arr) {
pre_sum = new Array(N + 1).fill(0);
 
// Finding prefix sum of array arr[]
for (let i = 1; i <= N; i++)
pre_sum[i] = pre_sum[i - 1] + arr[i - 1];
 
// Initializing DP with -1
for (let i = 0; i < dp.length; i++)
for (let j = 0; j < dp[i].length; j++)
dp[i][j].fill(-1);
 
// Copying n to global B
B = N + 1;
 
// Function to find maximum
return solve(K, 0, 1, arr);
}
 
// Driver code
let arr1 = [4, 1, -3, 7, -5, 6, -2, 1];
let K1 = 3;
let N1 = arr1.length;
 
// Function call
console.log(maxSum(K1, N1, arr1));
 
let arr2 = [8, -1, 4, 2, 6, -6, 4, -1];
let K2 = 2;
let N2 = arr2.length;
 
// Function call
console.log(maxSum(K2, N2, arr2));


Output

18
23

Time Complexity: O(N*K)
Auxiliary Space: O(N*K)

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Implementation :
 

C++




#include <bits/stdc++.h>
using namespace std;
 
int maxSum(int K, int N, int arr[])
{
    vector<int> pre_sum(N + 1, 0);
 
    // Finding prefix sum of array arr[]
    for (int i = 1; i <= N; i++)
        pre_sum[i] = pre_sum[i - 1] + arr[i - 1];
 
    // Initializing DP table with 0
    int dp[N + 1][K + 1];
    memset(dp, 0, sizeof(dp));
 
    // dp table to find maximum sum of k non-overlapping subarrays
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= K; j++) {
            int curr_max = INT_MIN;
            for (int k = i - 1; k >= j - 1; k--) {
                curr_max = max(curr_max, pre_sum[i] - pre_sum[k]);
                dp[i][j] = max(dp[i][j], dp[k][j - 1] + curr_max);
            }
        }
    }
 
    // Return the maximum sum
    return dp[N][K]+1;
}
 
// Driver code
int main()
{
    // Test case 1
    int arr1[] = { 4, 1, -3, 7, -5, 6, -2, 1 };
    int K1 = 3;
    int N1 = sizeof(arr1) / sizeof(arr1[0]);
 
    // Function call
    cout << maxSum(K1, N1, arr1) << endl;
 
    // Test case 2
    int arr2[] = { 8, -1, 4, 2, 6, -6, 4, -1 };
    int K2 = 2;
    int N2 = sizeof(arr2) / sizeof(arr2[0]);
 
    // Function call
    cout << maxSum(K2, N2, arr2);
    return 0;
}


Output

18
23

Time Complexity: O(N*K)
Auxiliary Space: O(N*K)


My Personal Notes arrow_drop_up
Last Updated : 19 May, 2023
Like Article
Save Article
Similar Reads
Related Tutorials