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:

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)