Maximum sum of at most K nonoverlapping Subarray (original) (raw)
Maximum sum of at most K non-overlapping Subarray
Last Updated : 30 Nov, 2023
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 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(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 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 pre_sum = new List();
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));
`
**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 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));
`
**Time Complexity: O(N*K)
**Auxiliary Space: O(N*K)