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++
// C++ program to find maximum sum possible // such that exactly floor(N/2) elements // are selected and no two selected // elements are adjacent to each other #include <bits/stdc++.h> using namespace std; // Function return the maximum sum // possible under given condition int MaximumSum( int a[], int n) { int dp[n + 1][n + 1]; // Intitialising the dp table for ( int i = 0; i < n + 1; i++) { for ( int j = 0; j < n + 1; j++) dp[i][j] = INT_MIN; } // Base case 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; // Condition to select the current // element 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); } // Condition to not select the // current element if possible if (i - 1 >= j) { val = max(val, dp[i - 1][j]); } dp[i][j] = val; } } return dp[n][n / 2]; } //Driver code int main() { int A[] = {1, 2, 3, 4, 5, 6}; int N = sizeof (A) / sizeof (A[0]); cout << MaximumSum(A, N); return 0; } |
Java
// Java program to find maximum sum possible // such that exactly Math.floor(N/2) elements // are selected and no two selected // elements are adjacent to each other class GFG{ // Function return the maximum sum // possible under given condition static int MaximumSum( int a[], int n) { int [][]dp = new int [n + 1 ][n + 1 ]; // Intitialising the dp table for ( int i = 0 ; i < n + 1 ; i++) { for ( int j = 0 ; j < n + 1 ; j++) dp[i][j] = Integer.MIN_VALUE; } // Base case 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; // Condition to select the current // element 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 ); } // Condition to not select the // current element if possible if (i - 1 >= j) { val = Math.max(val, dp[i - 1 ][j]); } dp[i][j] = val; } } return dp[n][n / 2 ]; } // Driver code public static void main(String[] args) { int A[] = { 1 , 2 , 3 , 4 , 5 , 6 }; int N = A.length; System.out.print(MaximumSum(A, N)); } } // This code is contributed by Rajput-Ji |
Python3
# Python3 program to find maximum sum possible # such that exactly floor(N/2) elements # are selected and no two selected # elements are adjacent to each other import sys # Function return the maximum sum # possible under given condition def MaximumSum(a,n): dp = [[ 0 for i in range (n + 1 )] for j in range (n + 1 )] # Intitialising the dp table for i in range (n + 1 ): for j in range (n + 1 ): dp[i][j] = - sys.maxsize - 1 # Base case 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 # Condition to select the current # element 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 ] # Condition to not select the # current element if possible if (i - 1 > = j): val = max (val, dp[i - 1 ][j]) dp[i][j] = val return dp[n][n / / 2 ] #Driver code if __name__ = = '__main__' : A = [ 1 , 2 , 3 , 4 , 5 , 6 ] N = len (A) print (MaximumSum(A,N)) # This code is contributed by Bhupendra_Singh |
C#
// C# program to find maximum sum possible // such that exactly Math.floor(N/2) elements // are selected and no two selected // elements are adjacent to each other using System; class GFG{ // Function return the maximum sum // possible under given condition static int MaximumSum( int []a, int n) { int [,]dp = new int [n + 1, n + 1]; // Intitialising the dp table for ( int i = 0; i < n + 1; i++) { for ( int j = 0; j < n + 1; j++) dp[i, j] = Int32.MinValue; } // Base case 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; // Condition to select the current // element 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); } // Condition to not select the // current element if possible if (i - 1 >= j) { val = Math.Max(val, dp[i - 1, j]); } dp[i, j] = val; } } return dp[n, n / 2]; } // Driver code public static void Main() { int []A = { 1, 2, 3, 4, 5, 6 }; int N = A.Length; Console.Write(MaximumSum(A, N)); } } // This code is contributed by Nidhi_biet |
Javascript
<script> // JavaScript program to find maximum sum possible // such that exactly Math.floor(N/2) elements // are selected and no two selected // elements are adjacent to each other // Function return the maximum sum // possible under given condition function MaximumSum(a,n) { let dp = []; for (let i=0;i<n+1;i++) dp.push(Array(n+1)); // Intitialising the dp table for (let i = 0; i < n + 1; i++) { for (let j = 0; j < n + 1; j++) dp[i][j] = -10000; } // Base case 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; // Condition to select the current // element 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); } // Condition to not select the // current element if possible if (i - 1 >= j) { val = Math.max(val, dp[i - 1][j]); } dp[i][j] = val; } } return dp[n][n / 2] } // Driver code let A = [1, 2, 3, 4, 5, 6]; let N = A.length; document.write(MaximumSum(A, N)); // This code is contributed by Nidhi_biet </script> |
12
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++
// C++ program to find maximum sum possible // such that exactly floor(N/2) elements // are selected and no two selected // elements are adjacent to each other #include <bits/stdc++.h> using namespace std; // Function return the maximum sum // possible under given condition int MaximumSum( int a[], int n) { int dp[n + 1][2]; // Intitialising the dp table memset (dp, 0, sizeof (dp)); // Base case dp[2][1] = a[1]; dp[2][0] = a[0]; for ( int i = 3; i < n + 1; i++) { // When i is odd 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] }); } // When i is even 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]; } } // Maximum of if we pick last element or not return max(dp[n][1], dp[n][0]); } // Driver code int main() { int A[] = {1, 2, 3, 4, 5, 6}; int N = sizeof (A) / sizeof (A[0]); cout << MaximumSum(A, N); return 0; } |
Java
// Java program to find maximum sum possible // such that exactly Math.floor(N/2) elements // are selected and no two selected // elements are adjacent to each other import java.util.*; class GFG{ // Function return the maximum sum // possible under given condition static int MaximumSum( int a[], int n) { int [][]dp = new int [n + 1 ][ 2 ]; // Base case dp[ 2 ][ 1 ] = a[ 1 ]; dp[ 2 ][ 0 ] = a[ 0 ]; for ( int i = 3 ; i < n + 1 ; i++) { // When i is odd 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 ])); } // When i is even 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 ]; } } // Maximum of if we pick last element or not return Math.max(dp[n][ 1 ], dp[n][ 0 ]); } static int max( int []arr) { return 1 ; } // Driver code public static void main(String[] args) { int A[] = { 1 , 2 , 3 , 4 , 5 , 6 }; int N = A.length; System.out.print(MaximumSum(A, N)); } } // This code is contributed by Rajput-Ji |
Python3
# Python3 program to find maximum sum possible # such that exactly floor(N/2) elements # are selected and no two selected # elements are adjacent to each other # Function return the maximum sum # possible under given condition def MaximumSum(a, n): dp = [[ 0 for x in range ( 2 )] for y in range (n + 1 )] # Base case dp[ 2 ][ 1 ] = a[ 1 ] dp[ 2 ][ 0 ] = a[ 0 ] for i in range ( 3 , n + 1 ): # When i is odd 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 ]]) # When i is even 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 ] # Maximum of if we pick last # element or not return max (dp[n][ 1 ], dp[n][ 0 ]) # Driver code if __name__ = = "__main__" : A = [ 1 , 2 , 3 , 4 , 5 , 6 ] N = len (A) print (MaximumSum(A, N)) # This code is contributed by Chitranayal |
C#
// C# program to find maximum sum possible // such that exactly Math.Floor(N/2) elements // are selected and no two selected // elements are adjacent to each other using System; class GFG{ // Function return the maximum sum // possible under given condition static int MaximumSum( int []a, int n) { int [,]dp = new int [n + 1, 2]; // Base case dp[2, 1] = a[1]; dp[2, 0] = a[0]; for ( int i = 3; i < n + 1; i++) { // When i is odd 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])); } // When i is even 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]; } } // Maximum of if we pick last element or not return Math.Max(dp[n, 1], dp[n, 0]); } static int max( int []arr) { return 1; } // Driver code public static void Main(String[] args) { int []A = { 1, 2, 3, 4, 5, 6 }; int N = A.Length; Console.Write(MaximumSum(A, N)); } } // This code is contributed by 29AjayKumar |
Javascript
<script> // Javascript program to find maximum sum possible // such that exactly floor(N/2) elements // are selected and no two selected // elements are adjacent to each other // Function return the maximum sum // possible under given condition function MaximumSum(a, n) { var dp = Array.from(Array(n+1), ()=>Array(2).fill(0)); // Base case dp[2][1] = a[1]; dp[2][0] = a[0]; for ( var i = 3; i < n + 1; i++) { // When i is odd 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))); } // When i is even 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]; } } // Maximum of if we pick last element or not return Math.max(dp[n][1], dp[n][0]); } // Driver code var A = [1, 2, 3, 4, 5, 6]; var N = A.length; document.write( MaximumSum(A, N)); </script> |
12
Time Complexity: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!