Given an array A containing N integers. Find the maximum sum possible such that exact floor(N/2) elements are selected and no two selected elements are adjacent to each other. (if N = 5, then exactly 2 elements should be selected as floor(5/2) = 2)
For a simpler version of this problem check out this.
Examples:
Input: A = [1, 2, 3, 4, 5, 6]
Output: 12
Explanation:
Select 2, 4 and 6 making the sum 12.
Input : A = [-1000, -100, -10, 0, 10]
Output : 0
Explanation:
Select -10 and 10, making the sum 0.
Approach:
- We will use the concept of dynamic programming. The following is how the dp states are defined:
dp[i][j] = maximum sum till index i such that j elements are selected
- Since no two adjacent elements can be selected :
dp[i][j] = max(a[i] + dp[i-2][j-1], dp[i-1][j])
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int MaximumSum( int a[], int n)
{
int dp[n + 1][n + 1];
for ( int i = 0; i < n + 1; i++)
{
for ( int j = 0; j < n + 1; j++)
dp[i][j] = INT_MIN;
}
for ( int i = 0; i < n + 1; i++)
dp[i][0] = 0;
for ( int i = 1; i <= n; i++)
{
for ( int j = 1; j <= i; j++)
{
int val = INT_MIN;
if ((i - 2 >= 0
&& dp[i - 2][j - 1] != INT_MIN)
|| i - 2 < 0)
{
val = a[i - 1] +
(i - 2 >= 0 ?
dp[i - 2][j - 1] : 0);
}
if (i - 1 >= j)
{
val = max(val, dp[i - 1][j]);
}
dp[i][j] = val;
}
}
return dp[n][n / 2];
}
int main()
{
int A[] = {1, 2, 3, 4, 5, 6};
int N = sizeof (A) / sizeof (A[0]);
cout << MaximumSum(A, N);
return 0;
}
|
Java
class GFG{
static int MaximumSum( int a[], int n)
{
int [][]dp = new int [n + 1 ][n + 1 ];
for ( int i = 0 ; i < n + 1 ; i++)
{
for ( int j = 0 ; j < n + 1 ; j++)
dp[i][j] = Integer.MIN_VALUE;
}
for ( int i = 0 ; i < n + 1 ; i++)
dp[i][ 0 ] = 0 ;
for ( int i = 1 ; i <= n; i++)
{
for ( int j = 1 ; j <= i; j++)
{
int val = Integer.MIN_VALUE;
if ((i - 2 >= 0 &&
dp[i - 2 ][j - 1 ] != Integer.MIN_VALUE) ||
i - 2 < 0 )
{
val = a[i - 1 ] + (i - 2 >= 0 ?
dp[i - 2 ][j - 1 ] : 0 );
}
if (i - 1 >= j)
{
val = Math.max(val, dp[i - 1 ][j]);
}
dp[i][j] = val;
}
}
return dp[n][n / 2 ];
}
public static void main(String[] args)
{
int A[] = { 1 , 2 , 3 , 4 , 5 , 6 };
int N = A.length;
System.out.print(MaximumSum(A, N));
}
}
|
Python3
import sys
def MaximumSum(a,n):
dp = [[ 0 for i in range (n + 1 )] for j in range (n + 1 )]
for i in range (n + 1 ):
for j in range (n + 1 ):
dp[i][j] = - sys.maxsize - 1
for i in range (n + 1 ):
dp[i][ 0 ] = 0
for i in range ( 1 ,n + 1 , 1 ):
for j in range ( 1 ,i + 1 , 1 ):
val = - sys.maxsize - 1
if ((i - 2 > = 0 and dp[i - 2 ][j - 1 ] ! = - sys.maxsize - 1 ) or i - 2 < 0 ):
if (i - 2 > = 0 ):
val = a[i - 1 ] + dp[i - 2 ][j - 1 ]
else :
val = a[i - 1 ]
if (i - 1 > = j):
val = max (val, dp[i - 1 ][j])
dp[i][j] = val
return dp[n][n / / 2 ]
if __name__ = = '__main__' :
A = [ 1 , 2 , 3 , 4 , 5 , 6 ]
N = len (A)
print (MaximumSum(A,N))
|
C#
using System;
class GFG{
static int MaximumSum( int []a, int n)
{
int [,]dp = new int [n + 1, n + 1];
for ( int i = 0; i < n + 1; i++)
{
for ( int j = 0; j < n + 1; j++)
dp[i, j] = Int32.MinValue;
}
for ( int i = 0; i < n + 1; i++)
dp[i, 0] = 0;
for ( int i = 1; i <= n; i++)
{
for ( int j = 1; j <= i; j++)
{
int val = Int32.MinValue;
if ((i - 2 >= 0 &&
dp[i - 2, j - 1] != Int32.MinValue) ||
i - 2 < 0)
{
val = a[i - 1] + (i - 2 >= 0 ?
dp[i - 2, j - 1] : 0);
}
if (i - 1 >= j)
{
val = Math.Max(val, dp[i - 1, j]);
}
dp[i, j] = val;
}
}
return dp[n, n / 2];
}
public static void Main()
{
int []A = { 1, 2, 3, 4, 5, 6 };
int N = A.Length;
Console.Write(MaximumSum(A, N));
}
}
|
Javascript
<script>
function MaximumSum(a,n)
{
let dp = [];
for (let i=0;i<n+1;i++) dp.push(Array(n+1));
for (let i = 0; i < n + 1; i++)
{
for (let j = 0; j < n + 1; j++)
dp[i][j] = -10000;
}
for (let i = 0; i < n + 1; i++)
dp[i][0] = 0;
for (let i = 1; i <= n; i++)
{
for (let j = 1; j <= i; j++)
{
let val = -10000;
if ((i - 2 >= 0 &&
dp[i - 2, j - 1] != -10000) ||
i - 2 < 0)
{
val = a[i - 1] + (i - 2 >= 0 ?
dp[i - 2][j - 1] : 0);
}
if (i - 1 >= j)
{
val = Math.max(val, dp[i - 1][j]);
}
dp[i][j] = val;
}
}
return dp[n][n / 2]
}
let A = [1, 2, 3, 4, 5, 6];
let N = A.length;
document.write(MaximumSum(A, N));
</script>
|
Time Complexity : O(N2)
Efficient Approach
- We will use dynamic programming but with slightly modified states. Storing both the index and is number of elements taken till now are futile since we always need to take exact floor(i/2) elements, so at i’th position for the dp storage we will assume floor(i/2) elements in the subset till now.
- The following is the dp table states:
dp[i][1] = maximum sum till i’th index, picking element a[i], with floor(i/2) elements, none adjacent to each other.
dp[i][0] = maximum sum till i’th index, not picking element a[i], with floor(i/2) elements, none adjacent to each other.
- We have two cases :
- When i is odd : If we have to pick a[i], then we can’t pick a[i-1], so the only options left are (i – 2)th and (i – 3) rd state (because floor((i – 2)/2) = floor((i – 3)/2) = floor(i/2) – 1, and since we pick a[i], total picked elements will be floor(i/2) ). If we don’t pick a[i], then a sum will be formed by taking a[i-1] and using states i – 1, i – 2 and i – 3 or a[i – 2] using state i – 3 as these will only give the total of floor(i/2).
dp[i][1] = arr[i] + max({dp[i – 3][1], dp[i – 3][0], dp[i – 2][1], dp[i – 2][0]})
dp[i][0] = max({arr[i – 1] + dp[i – 2][0], arr[i – 1] + dp[i – 3][1], arr[i – 1] + dp[i – 3][0],
arr[i – 2] + dp[i – 3][0]})
- When i is even : If we pick a[i], then using states i – 1 and i – 2, else picking a[i – 1] and using state i – 2.
dp[i][1] = arr[i] + max({dp[i – 2][1], dp[i – 2][0], dp[i – 1][0]})
dp[i][0] = arr[i – 1] + dp[i – 2][0]
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int MaximumSum( int a[], int n)
{
int dp[n + 1][2];
memset (dp, 0, sizeof (dp));
dp[2][1] = a[1];
dp[2][0] = a[0];
for ( int i = 3; i < n + 1; i++) {
if (i & 1) {
int temp = max({ dp[i - 3][1],
dp[i - 3][0],
dp[i - 2][1],
dp[i - 2][0] });
dp[i][1] = a[i - 1] + temp;
dp[i][0] = max({ a[i - 2] + dp[i - 2][0],
a[i - 2] + dp[i - 3][1],
a[i - 2] + dp[i - 3][0],
a[i - 3] + dp[i - 3][0] });
}
else {
dp[i][1] = a[i - 1] + max({ dp[i - 2][1],
dp[i - 2][0],
dp[i - 1][0] });
dp[i][0] = a[i - 2] + dp[i - 2][0];
}
}
return max(dp[n][1], dp[n][0]);
}
int main()
{
int A[] = {1, 2, 3, 4, 5, 6};
int N = sizeof (A) / sizeof (A[0]);
cout << MaximumSum(A, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int MaximumSum( int a[], int n)
{
int [][]dp = new int [n + 1 ][ 2 ];
dp[ 2 ][ 1 ] = a[ 1 ];
dp[ 2 ][ 0 ] = a[ 0 ];
for ( int i = 3 ; i < n + 1 ; i++)
{
if (i % 2 == 1 )
{
int temp = Math.max((Math.max(dp[i - 3 ][ 1 ],
dp[i - 3 ][ 0 ])),
Math.max(dp[i - 2 ][ 1 ],
dp[i - 2 ][ 0 ]));
dp[i][ 1 ] = a[i - 1 ] + temp;
dp[i][ 0 ] = Math.max((Math.max(a[i - 2 ] +
dp[i - 2 ][ 0 ],
a[i - 2 ] +
dp[i - 3 ][ 1 ])),
Math.max(a[i - 2 ] +
dp[i - 3 ][ 0 ],
a[i - 3 ] +
dp[i - 3 ][ 0 ]));
}
else
{
dp[i][ 1 ] = a[i - 1 ] + (Math.max((
Math.max(dp[i - 2 ][ 1 ],
dp[i - 2 ][ 0 ])),
dp[i - 1 ][ 0 ]));
dp[i][ 0 ] = a[i - 2 ] + dp[i - 2 ][ 0 ];
}
}
return Math.max(dp[n][ 1 ], dp[n][ 0 ]);
}
static int max( int []arr)
{
return 1 ;
}
public static void main(String[] args)
{
int A[] = { 1 , 2 , 3 , 4 , 5 , 6 };
int N = A.length;
System.out.print(MaximumSum(A, N));
}
}
|
Python3
def MaximumSum(a, n):
dp = [[ 0 for x in range ( 2 )]
for y in range (n + 1 )]
dp[ 2 ][ 1 ] = a[ 1 ]
dp[ 2 ][ 0 ] = a[ 0 ]
for i in range ( 3 , n + 1 ):
if (i & 1 ):
temp = max ([dp[i - 3 ][ 1 ],
dp[i - 3 ][ 0 ],
dp[i - 2 ][ 1 ],
dp[i - 2 ][ 0 ]])
dp[i][ 1 ] = a[i - 1 ] + temp
dp[i][ 0 ] = max ([a[i - 2 ] + dp[i - 2 ][ 0 ],
a[i - 2 ] + dp[i - 3 ][ 1 ],
a[i - 2 ] + dp[i - 3 ][ 0 ],
a[i - 3 ] + dp[i - 3 ][ 0 ]])
else :
dp[i][ 1 ] = (a[i - 1 ] + max ([dp[i - 2 ][ 1 ],
dp[i - 2 ][ 0 ],
dp[i - 1 ][ 0 ]]))
dp[i][ 0 ] = a[i - 2 ] + dp[i - 2 ][ 0 ]
return max (dp[n][ 1 ], dp[n][ 0 ])
if __name__ = = "__main__" :
A = [ 1 , 2 , 3 , 4 , 5 , 6 ]
N = len (A)
print (MaximumSum(A, N))
|
C#
using System;
class GFG{
static int MaximumSum( int []a, int n)
{
int [,]dp = new int [n + 1, 2];
dp[2, 1] = a[1];
dp[2, 0] = a[0];
for ( int i = 3; i < n + 1; i++)
{
if (i % 2 == 1)
{
int temp = Math.Max((Math.Max(dp[i - 3, 1],
dp[i - 3, 0])),
Math.Max(dp[i - 2, 1],
dp[i - 2, 0]));
dp[i, 1] = a[i - 1] + temp;
dp[i, 0] = Math.Max((Math.Max(a[i - 2] +
dp[i - 2, 0],
a[i - 2] +
dp[i - 3, 1])),
Math.Max(a[i - 2] +
dp[i - 3, 0],
a[i - 3] +
dp[i - 3, 0]));
}
else
{
dp[i, 1] = a[i - 1] + (Math.Max((
Math.Max(dp[i - 2, 1],
dp[i - 2, 0])),
dp[i - 1, 0]));
dp[i, 0] = a[i - 2] + dp[i - 2, 0];
}
}
return Math.Max(dp[n, 1], dp[n, 0]);
}
static int max( int []arr)
{
return 1;
}
public static void Main(String[] args)
{
int []A = { 1, 2, 3, 4, 5, 6 };
int N = A.Length;
Console.Write(MaximumSum(A, N));
}
}
|
Javascript
<script>
function MaximumSum(a, n)
{
var dp = Array.from(Array(n+1), ()=>Array(2).fill(0));
dp[2][1] = a[1];
dp[2][0] = a[0];
for ( var i = 3; i < n + 1; i++) {
if (i & 1) {
var temp = ([dp[i - 3][1],
dp[i - 3][0],
dp[i - 2][1],
dp[i - 2][0] ].reduce((a,b)=>
Math.max(a,b)));
dp[i][1] = a[i - 1] + temp;
dp[i][0] = ([ a[i - 2] + dp[i - 2][0],
a[i - 2] + dp[i - 3][1],
a[i - 2] + dp[i - 3][0],
a[i - 3] + dp[i - 3][0] ].reduce((a,b)=>
Math.max(a,b)));
}
else {
dp[i][1] = a[i - 1] + ([ dp[i - 2][1],
dp[i - 2][0],
dp[i - 1][0] ].reduce((a,b)=>
Math.max(a,b)));
dp[i][0] = a[i - 2] + dp[i - 2][0];
}
}
return Math.max(dp[n][1], dp[n][0]);
}
var A = [1, 2, 3, 4, 5, 6];
var N = A.length;
document.write( MaximumSum(A, N));
</script>
|
Time Complexity: O(N)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!