Given an integer array ‘arr’ of length N and an integer ‘k’, select some non-overlapping subarrays such that each sub-array if of length at most ‘k’, no two sub-arrays are adjacent and sum of all the elements of the selected sub-arrays are maximum.
Examples:
Input : arr[] = {-1, 2, -3, 4, 5}, k = 2 Output : 11 Sub-arrays that maximizes sum will be {{2}, {4, 5}}. Thus, the answer will be 2+4+5 = 11. Input :arr[] = {1, 1, 1, 1, 1}, k = 1 Output : 3
Naive Approach : A simple way is to generate all possible subsets of elements satisfying above conditions recursively and find the subset with maximum sum.
Time Complexity : O(2N)
Efficient Approach: A better approach is to use dynamic programming.
Let’s suppose we are at an index ‘i’.
Let dp[i] be defined as the maximum sum of elements of all possible subsets of sub-array {i, n-1} satisfying above conditions.
We will have ‘K+1’ possible choices i.e.
- Reject ‘i’ and solve for ‘i+1’.
- Select sub-array {i} and solve for ‘i+2’
- Select sub-array {i, i+1} and solve for ‘i+3’
Thus, recurrence relation will be:
dp[i] = max(dp[i+1], arr[i]+dp[i+2], arr[i]+arr[i+1]+dp[i+3], ...arr[i]+arr[i+1]+arr[i+2]...+arr[i+k-1] + dp[i+k+1])
Below is the implementation of the above approach:
// C++ program to implement above approach #include <bits/stdc++.h> #define maxLen 10 using namespace std;
// Variable to store states of dp int dp[maxLen];
// Variable to check if a given state has been solved bool visit[maxLen];
// Function to find the maximum sum subsequence // such that no two elements are adjacent int maxSum( int arr[], int i, int n, int k)
{ // Base case
if (i >= n)
return 0;
// To check if a state has been solved
if (visit[i])
return dp[i];
visit[i] = 1;
// Variable to store
// prefix sum for sub-array
// {i, j}
int tot = 0;
dp[i] = maxSum(arr, i + 1, n, k);
// Required recurrence relation
for ( int j = i; j < i + k and j < n; j++) {
tot += arr[j];
dp[i] = max(dp[i], tot +
maxSum(arr, j + 2, n, k));
}
// Returning the value
return dp[i];
} // Driver code int main()
{ // Input array
int arr[] = { -1, 2, -3, 4, 5 };
int k = 2;
int n = sizeof (arr) / sizeof ( int );
cout << maxSum(arr, 0, n, k);
return 0;
} |
// Java program to implement above approach import java.io.*;
class GFG
{ static int maxLen = 10 ;
// Variable to store states of dp
static int dp[] = new int [maxLen];
// Variable to check
// if a given state has been solved
static boolean []visit = new boolean [maxLen];
// Function to find the maximum sum subsequence
// such that no two elements are adjacent
static int maxSum( int arr[], int i,
int n, int k)
{
// Base case
if (i >= n)
return 0 ;
// To check if a state has been solved
if (visit[i])
return dp[i];
visit[i] = true ;
// Variable to store
// prefix sum for sub-array
// {i, j}
int tot = 0 ;
dp[i] = maxSum(arr, i + 1 , n, k);
// Required recurrence relation
for ( int j = i; j < (i + k) &&
(j < n); j++)
{
tot += arr[j];
dp[i] = Math.max(dp[i], tot +
maxSum(arr, j + 2 , n, k));
}
// Returning the value
return dp[i];
}
// Driver code
public static void main (String[] args)
{
// Input array
int arr[] = { - 1 , 2 , - 3 , 4 , 5 };
int k = 2 ;
int n = arr.length;
System.out.println(maxSum(arr, 0 , n, k));
}
} // This code is contributed by ajit. |
# Python3 program to implement above approach maxLen = 10
# Variable to store states of dp dp = [ 0 ] * maxLen;
# Variable to check if a given state has been solved visit = [ 0 ] * maxLen;
# Function to find the maximum sum subsequence # such that no two elements are adjacent def maxSum(arr, i, n, k) :
# Base case
if (i > = n) :
return 0 ;
# To check if a state has been solved
if (visit[i]) :
return dp[i];
visit[i] = 1 ;
# Variable to store
# prefix sum for sub-array
# {i, j}
tot = 0 ;
dp[i] = maxSum(arr, i + 1 , n, k);
# Required recurrence relation
j = i
while (j < i + k and j < n) :
tot + = arr[j];
dp[i] = max (dp[i], tot +
maxSum(arr, j + 2 , n, k));
j + = 1
# Returning the value
return dp[i];
# Driver code if __name__ = = "__main__" :
# Input array
arr = [ - 1 , 2 , - 3 , 4 , 5 ];
k = 2 ;
n = len (arr);
print (maxSum(arr, 0 , n, k));
# This code is contributed by AnkitRai01 |
// C# program to implement above approach using System;
class GFG
{ static int maxLen = 10;
// Variable to store states of dp static int []dp = new int [maxLen];
// Variable to check // if a given state has been solved static bool []visit = new bool [maxLen];
// Function to find the maximum sum subsequence // such that no two elements are adjacent static int maxSum( int []arr, int i,
int n, int k)
{ // Base case
if (i >= n)
return 0;
// To check if a state has been solved
if (visit[i])
return dp[i];
visit[i] = true ;
// Variable to store
// prefix sum for sub-array
// {i, j}
int tot = 0;
dp[i] = maxSum(arr, i + 1, n, k);
// Required recurrence relation
for ( int j = i; j < (i + k) &&
(j < n); j++)
{
tot += arr[j];
dp[i] = Math.Max(dp[i], tot +
maxSum(arr, j + 2, n, k));
}
// Returning the value
return dp[i];
} // Driver code static public void Main ()
{ // Input array
int []arr = { -1, 2, -3, 4, 5 };
int k = 2;
int n = arr.Length;
Console.WriteLine (maxSum(arr, 0, n, k));
} } // This code is contributed by ajit. |
<script> // Javascript program to implement above approach
let maxLen = 10;
// Variable to store states of dp
let dp = new Array(maxLen);
// Variable to check
// if a given state has been solved
let visit = new Array(maxLen);
// Function to find the maximum sum subsequence
// such that no two elements are adjacent
function maxSum(arr, i, n, k)
{
// Base case
if (i >= n)
return 0;
// To check if a state has been solved
if (visit[i])
return dp[i];
visit[i] = true ;
// Variable to store
// prefix sum for sub-array
// {i, j}
let tot = 0;
dp[i] = maxSum(arr, i + 1, n, k);
// Required recurrence relation
for (let j = i; j < (i + k) &&
(j < n); j++)
{
tot += arr[j];
dp[i] = Math.max(dp[i], tot +
maxSum(arr, j + 2, n, k));
}
// Returning the value
return dp[i];
}
// Input array
let arr = [ -1, 2, -3, 4, 5 ];
let k = 2;
let n = arr.length;
document.write(maxSum(arr, 0, n, k));
</script> |
11
Time Complexity: O(n*k)
Space complexity: O(n)
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.
Steps to solve this problem :
- Create a 1D DP of size n to store the solution of the subproblems.
- Initialize the DP with 0.
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
- Create a variable res and to store the final result and update it by iterating through Dp.
- Return the final solution stored in res
Implementation :
#include <bits/stdc++.h> #define maxLen 10 using namespace std;
// Function to find the maximum sum subsequence // such that no two elements are adjacent int maxSum( int arr[], int n, int k)
{ // DP table
int dp[n];
// Initializing the DP table
memset (dp, 0, sizeof (dp));
// Computing the DP table
for ( int i = 0; i < n; i++) {
int tot = 0;
for ( int j = i - k; j < i; j++) {
if (j >= 0)
tot = max(tot, dp[j]);
}
dp[i] = tot + arr[i];
}
// Returning the maximum sum
int res = 0;
for ( int i = 0; i < n; i++)
res = max(res, dp[i]);
// return final ans
return res;
} // Driver code int main()
{ // Input array
int arr[] = { -1, 2, -3, 4, 5 };
int k = 2;
int n = sizeof (arr) / sizeof ( int );
cout << maxSum(arr, n, k);
return 0;
} |
import java.util.Arrays;
class GFG
{ // Function to find the maximum sum subsequence
// such that no two elements are adjacent
static int maxSum( int arr[], int n, int k)
{
// DP table
int dp[] = new int [n];
// Initializing the DP table
Arrays.fill(dp, 0 );
// Computing the DP table
for ( int i = 0 ; i < n; i++) {
int tot = 0 ;
for ( int j = i - k; j < i; j++) {
if (j >= 0 )
tot = Math.max(tot, dp[j]);
}
dp[i] = tot + arr[i];
}
// Returning the maximum sum
int res = 0 ;
for ( int i = 0 ; i < n; i++)
res = Math.max(res, dp[i]);
// return final ans
return res;
}
// Driver code
public static void main(String[] args)
{
// Input array
int arr[] = { - 1 , 2 , - 3 , 4 , 5 };
int k = 2 ;
int n = arr.length;
System.out.println(maxSum(arr, n, k));
}
} |
def maxSum(arr, n, k):
# DP table
dp = [ 0 ] * n
# Computing the DP table
for i in range (n):
tot = 0
for j in range (i - k, i):
if j > = 0 :
tot = max (tot, dp[j])
dp[i] = tot + arr[i]
# Returning the maximum sum
res = 0
for i in range (n):
res = max (res, dp[i])
# return final ans
return res
# Driver code arr = [ - 1 , 2 , - 3 , 4 , 5 ]
k = 2
n = len (arr)
print (maxSum(arr, n, k))
|
using System;
class MaxSum
{ static int ComputeMaxSum( int [] arr, int n, int k)
{
// DP table
int [] dp = new int [n];
// Computing the DP table
for ( int i = 0; i < n; i++)
{
int tot = 0;
for ( int j = i - k; j < i; j++)
{
if (j >= 0)
{
tot = Math.Max(tot, dp[j]);
}
}
dp[i] = tot + arr[i];
}
// Returning the maximum sum
int res = 0;
for ( int i = 0; i < n; i++)
{
res = Math.Max(res, dp[i]);
}
// return final ans
return res;
}
static void Main()
{
int [] arr = {-1, 2, -3, 4, 5};
int k = 2;
int n = arr.Length;
Console.WriteLine(ComputeMaxSum(arr, n, k));
}
} |
// Function to find the maximum sum subsequence // such that no two elements are adjacent function maxSum(arr, n, k)
{ // DP table
let dp = new Array(n);
// Initializing the DP table
dp.fill(0);
// Computing the DP table
for (let i = 0; i < n; i++) {
let tot = 0;
for (let j = i - k; j < i; j++) {
if (j >= 0)
tot = Math.max(tot, dp[j]);
}
dp[i] = tot + arr[i];
}
// Returning the maximum sum
let res = 0;
for (let i = 0; i < n; i++)
res = Math.max(res, dp[i]);
// return final ans
return res;
} // Driver code function main()
{ // Input array
let arr = [ -1, 2, -3, 4, 5 ];
let k = 2;
let n = arr.length;
console.log(maxSum(arr, n, k));
} main(); |
Output
11
Time Complexity: O(n*k)
Auxiliary Space: O(n)