Open In App
Related Articles

Maximum sum of at most K non-overlapping Subarray

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

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)

                    

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))

                    

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

                    

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;
}

                    

Java

import java.util.Arrays;
 
public class MaxSumSubarrays {
 
    // Function to find the maximum sum of K non-overlapping subarrays
    static int maxSum(int K, int N, int[] arr) {
        // Creating an array to store prefix sum of arr[]
        int[] preSum = new int[N + 1];
 
        // Finding prefix sum of array arr[]
        for (int i = 1; i <= N; i++)
            preSum[i] = preSum[i - 1] + arr[i - 1];
 
        // Initializing DP table with 0
        int[][] dp = new int[N + 1][K + 1];
        for (int[] row : dp)
            Arrays.fill(row, 0);
 
        // 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 currMax = Integer.MIN_VALUE;
                for (int k = i - 1; k >= j - 1; k--) {
                    currMax = Math.max(currMax, preSum[i] - preSum[k]);
                    dp[i][j] = Math.max(dp[i][j], dp[k][j - 1] + currMax);
                }
            }
        }
 
        // Return the maximum sum
        return dp[N][K] + 1;
    }
 
    // 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));
    }
}

                    

Python3

def maxSum(K, N, arr):
    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 table with 0
    dp = [[0] * (K + 1) for _ in range(N + 1)]
     
    # dp table to find maximum sum of k non-overlapping subarrays
    for i in range(1, N + 1):
        for j in range(1, K + 1):
            curr_max = float('-inf')
            for k in range(i - 1, j - 2, -1):
                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
arr1 = [4, 1, -3, 7, -5, 6, -2, 1]
K1 = 3
N1 = len(arr1)
 
print(maxSum(K1, N1, arr1))
 
arr2 = [8, -1, 4, 2, 6, -6, 4, -1]
K2 = 2
N2 = len(arr2)
 
print(maxSum(K2, N2, arr2))

                    

C#

using System;
 
class GFG
{
    // Finding prefix sum of array [] arr
    static int MaxSum(int K, int N, int[] arr)
    {
        int[] preSum = new int[N + 1];
        // Calculate the prefix sum
        for (int i = 1; i <= N; i++)
            preSum[i] = preSum[i - 1] + arr[i - 1];
        int[,] dp = new int[N + 1, K + 1];
 
        // Initialize the DP table with 0
        for (int i = 0; i <= N; i++)
            for (int j = 0; j <= K; j++)
                dp[i, j] = 0;
        // DP table to find the maximum sum of K non-overlapping subarrays
        for (int i = 1; i <= N; i++)
        {
            for (int j = 1; j <= K; j++)
            {
                int currMax = int.MinValue;
                for (int k = i - 1; k >= j - 1; k--)
                {
                    currMax = Math.Max(currMax, preSum[i] - preSum[k]);
                    dp[i, j] = Math.Max(dp[i, j], dp[k, j - 1] + currMax);
                }
            }
        }
        // Return the maximum sum
        return dp[N, K] + 1;
    }
    static 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));
    }
}

                    

Javascript

function maxSum(K, N, arr)
{
    let 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 table with 0
    let dp = new Array(N + 1).fill().map(() => new Array(K + 1).fill(0));
 
    // dp table to find maximum sum of k non-overlapping subarrays
    for (let i = 1; i <= N; i++) {
        for (let j = 1; j <= K; j++) {
            let curr_max = Number.MIN_SAFE_INTEGER;
            for (let k = i - 1; k >= j - 1; k--) {
                curr_max = Math.max(curr_max, pre_sum[i] - pre_sum[k]);
                dp[i][j] = Math.max(dp[i][j], dp[k][j - 1] + curr_max);
            }
        }
    }
 
    // Return the maximum sum
    return dp[N][K]+1;
}
 
// Driver code
 
// Test case 1
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));
 
// Test case 2
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)



Last Updated : 30 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads