Given an array arr[] of integer elements, the task is to find maximum possible sub-array sum after changing the signs of at most two elements.
Examples:
Input: arr[] = {-5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6}
Output: 61
We can get 61 from index 0 to 10 by
changing the sign of elements at 4th and 7th indices i.e.
-8 and -9. We could have chosen -5 and -6 but this gives us
smaller sum 48.
Input: arr[] = {-5, -3, -18, 0, -4}
Output: 22
Approach: This problem can be solved using Dynamic Programming. Let’s suppose there are n elements in the array. We build our solution from smallest length to largest length.
At each step, we change the solution for length i to i+1.
For each step we have three cases:
- (Maximum sub-array sum) by altering sign of at most 0 element.
- (Maximum sub-array sum) by altering sign of at most 1 element.
- (Maximum sub-array sum) by altering sign of at most 2 element.
These cases use each others previous values.
- Case 1: We have two choices either to take current element or to add current value into previous value of same case.we store whichever is larger.
- Case 2: We have two choices here
- We alter the sign of current element and then add it to 0 or previous case 1 value. we store whichever is larger.
- we take the current element of array and add it to previous case 2 value.If this value is larger than value we get in (a) case then we update else not.
- Case 3: We again have two choices here
- We alter the sign of current element and add it to previous case 2 value.
- We add current element into previous case 3 value. Larger value obtained from (a) and (b) is stored for current case.
We update the max value out of these 3 cases and store it in a variable.
For each case of each step we take Two dimensional array dp[n+1][3] if given array contains n elements.
Recurrence Relation:
Case 1: dp[i][0] = max(dp[i – 1][0] + arr[i], arr[i])
Case 2: dp[i][1] = max(max(0, dp[i – 1][0]) – arr[i], dp[i – 1][1] + arr[i])
Case 3: dp[i][2] = max(dp[i – 1][1] – arr[i], dp[i – 1][2] + arr[i])
solution = max(solution, max(dp[i][0], dp[i][1], dp[i][2]))
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <algorithm> #include <iostream> using namespace std; // Function to return the maximum required sub-array sum int maxSum( int a[], int n) { int ans = 0; int * arr = new int [n + 1]; // Creating one based indexing for ( int i = 1; i <= n; i++) arr[i] = a[i - 1]; // 2d array to contain solution for each step int ** dp = new int *[n + 1]; for ( int i = 0; i <= n; i++) dp[i] = new int [3]; for ( int i = 1; i <= n; ++i) { // Case 1: Choosing current or (current + previous) // whichever is smaller dp[i][0] = max(arr[i], dp[i - 1][0] + arr[i]); // Case 2:(a) Altering sign and add to previous case 1 or // value 0 dp[i][1] = max(0, dp[i - 1][0]) - arr[i]; // Case 2:(b) Adding current element with previous case 2 // and updating the maximum if (i >= 2) dp[i][1] = max(dp[i][1], dp[i - 1][1] + arr[i]); // Case 3:(a) Altering sign and add to previous case 2 if (i >= 2) dp[i][2] = dp[i - 1][1] - arr[i]; // Case 3:(b) Adding current element with previous case 3 if (i >= 3) dp[i][2] = max(dp[i][2], dp[i - 1][2] + arr[i]); // Updating the maximum value of variable ans ans = max(ans, dp[i][0]); ans = max(ans, dp[i][1]); ans = max(ans, dp[i][2]); } // Return the final solution return ans; } // Driver code int main() { int arr[] = { -5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6 }; int n = sizeof (arr) / sizeof (arr[0]); cout << maxSum(arr, n); return 0; } |
Java
// Java implementation of the approach class GFG { // Function to return the maximum required sub-array sum static int maxSum( int []a, int n) { int ans = 0 ; int [] arr = new int [n + 1 ]; // Creating one based indexing for ( int i = 1 ; i <= n; i++) arr[i] = a[i - 1 ]; // 2d array to contain solution for each step int [][] dp = new int [n + 1 ][ 3 ]; for ( int i = 1 ; i <= n; ++i) { // Case 1: Choosing current or (current + previous) // whichever is smaller dp[i][ 0 ] = Math.max(arr[i], dp[i - 1 ][ 0 ] + arr[i]); // Case 2:(a) Altering sign and add to previous case 1 or // value 0 dp[i][ 1 ] = Math.max( 0 , dp[i - 1 ][ 0 ]) - arr[i]; // Case 2:(b) Adding current element with previous case 2 // and updating the maximum if (i >= 2 ) dp[i][ 1 ] = Math.max(dp[i][ 1 ], dp[i - 1 ][ 1 ] + arr[i]); // Case 3:(a) Altering sign and add to previous case 2 if (i >= 2 ) dp[i][ 2 ] = dp[i - 1 ][ 1 ] - arr[i]; // Case 3:(b) Adding current element with previous case 3 if (i >= 3 ) dp[i][ 2 ] = Math.max(dp[i][ 2 ], dp[i - 1 ][ 2 ] + arr[i]); // Updating the maximum value of variable ans ans = Math.max(ans, dp[i][ 0 ]); ans = Math.max(ans, dp[i][ 1 ]); ans = Math.max(ans, dp[i][ 2 ]); } // Return the final solution return ans; } // Driver code public static void main (String[] args) { int arr[] = { - 5 , 3 , 2 , 7 , - 8 , 3 , 7 , - 9 , 10 , 12 , - 6 }; int n = arr.length; System.out.println(maxSum(arr, n)); } } // This code is contributed by ihritik |
Python3
# Python3 implementation of the approach # Function to return the maximum # required sub-array sum def maxSum(a, n): ans = 0 arr = [ 0 ] * (n + 1 ) # Creating one based indexing for i in range ( 1 , n + 1 ): arr[i] = a[i - 1 ] # 2d array to contain solution for each step dp = [[ 0 for i in range ( 3 )] for j in range (n + 1 )] for i in range ( 0 , n + 1 ): # Case 1: Choosing current or # (current + previous) whichever is smaller dp[i][ 0 ] = max (arr[i], dp[i - 1 ][ 0 ] + arr[i]) # Case 2:(a) Altering sign and add to # previous case 1 or value 0 dp[i][ 1 ] = max ( 0 , dp[i - 1 ][ 0 ]) - arr[i] # Case 2:(b) Adding current element with # previous case 2 and updating the maximum if i > = 2 : dp[i][ 1 ] = max (dp[i][ 1 ], dp[i - 1 ][ 1 ] + arr[i]) # Case 3:(a) Altering sign and # add to previous case 2 if i > = 2 : dp[i][ 2 ] = dp[i - 1 ][ 1 ] - arr[i] # Case 3:(b) Adding current element # with previous case 3 if i > = 3 : dp[i][ 2 ] = max (dp[i][ 2 ], dp[i - 1 ][ 2 ] + arr[i]) # Updating the maximum value # of variable ans ans = max (ans, dp[i][ 0 ]) ans = max (ans, dp[i][ 1 ]) ans = max (ans, dp[i][ 2 ]) # Return the final solution return ans # Driver code if __name__ = = "__main__" : arr = [ - 5 , 3 , 2 , 7 , - 8 , 3 , 7 , - 9 , 10 , 12 , - 6 ] n = len (arr) print (maxSum(arr, n)) # This code is contributed by Rituraj Jain |
C#
// C# implementation of the approach using System; class GFG { // Function to return the maximum required sub-array sum static int maxSum( int [] a, int n) { int ans = 0; int [] arr = new int [n + 1]; // Creating one based indexing for ( int i = 1; i <= n; i++) arr[i] = a[i - 1]; // 2d array to contain solution for each step int [, ] dp = new int [n + 1, 3]; for ( int i = 1; i <= n; ++i) { // Case 1: Choosing current or (current + previous) // whichever is smaller dp[i, 0] = Math.Max(arr[i], dp[i - 1, 0] + arr[i]); // Case 2:(a) Altering sign and add to previous case 1 or // value 0 dp[i, 1] = Math.Max(0, dp[i - 1, 0]) - arr[i]; // Case 2:(b) Adding current element with previous case 2 // and updating the maximum if (i >= 2) dp[i, 1] = Math.Max(dp[i, 1], dp[i - 1, 1] + arr[i]); // Case 3:(a) Altering sign and add to previous case 2 if (i >= 2) dp[i, 2] = dp[i - 1, 1] - arr[i]; // Case 3:(b) Adding current element with previous case 3 if (i >= 3) dp[i, 2] = Math.Max(dp[i, 2], dp[i - 1, 2] + arr[i]); // Updating the maximum value of variable ans ans = Math.Max(ans, dp[i, 0]); ans = Math.Max(ans, dp[i, 1]); ans = Math.Max(ans, dp[i, 2]); } // Return the final solution return ans; } // Driver code public static void Main () { int [] arr = { -5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6 }; int n = arr.Length; Console.WriteLine(maxSum(arr, n)); } } // This code is contributed by ihritik |
PHP
<?php // PHP implementation of the approach // Function to return the maximum // required sub-array sum function maxSum( $a , $n ) { $ans = 0; $arr = array (); // Creating one based indexing for ( $i = 1; $i <= $n ; $i ++) $arr [ $i ] = $a [ $i - 1]; // 2d array to contain solution // for each step $dp = array ( array ()); for ( $i = 1; $i <= $n ; ++ $i ) { // Case 1: Choosing current or (current + // previous) whichever is smaller $dp [ $i ][0] = max( $arr [ $i ], $dp [ $i - 1][0] + $arr [ $i ]); // Case 2:(a) Altering sign and add to // previous case 1 or value 0 $dp [ $i ][1] = max(0, $dp [ $i - 1][0]) - $arr [ $i ]; // Case 2:(b) Adding current element with // previous case 2 and updating the maximum if ( $i >= 2) $dp [ $i ][1] = max( $dp [ $i ][1], $dp [ $i - 1][1] + $arr [ $i ]); // Case 3:(a) Altering sign and // add to previous case 2 if ( $i >= 2) $dp [ $i ][2] = $dp [ $i - 1][1] - $arr [ $i ]; // Case 3:(b) Adding current element // with previous case 3 if ( $i >= 3) $dp [ $i ][2] = max( $dp [ $i ][2], $dp [ $i - 1][2] + $arr [ $i ]); // Updating the maximum value of variable ans $ans = max( $ans , $dp [ $i ][0]); $ans = max( $ans , $dp [ $i ][1]); $ans = max( $ans , $dp [ $i ][2]); } // Return the final solution return $ans ; } // Driver code $arr = array ( -5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6 ); $n = count ( $arr ) ; echo maxSum( $arr , $n ); // This code is contributed by Ryuga ?> |
Javascript
<script> // JavaScript implementation of the approach // Function to return the maximum required sub-array sum function maxSum(a, n) { let ans = 0; let arr = new Array(n + 1); // Creating one based indexing for (let i = 1; i <= n; i++) arr[i] = a[i - 1]; // 2d array to contain solution for each step let dp = new Array(n + 1); for (let i = 0; i <= n; ++i) { dp[i] = new Array(3); for (let j = 0; j < 3; ++j) { dp[i][j] = 0; } } for (let i = 1; i <= n; ++i) { // Case 1: Choosing current or (current + previous) // whichever is smaller dp[i][0] = Math.max(arr[i], dp[i - 1][0] + arr[i]); // Case 2:(a) Altering sign and add to previous case 1 or // value 0 dp[i][1] = Math.max(0, dp[i - 1][0]) - arr[i]; // Case 2:(b) Adding current element with previous case 2 // and updating the maximum if (i >= 2) dp[i][1] = Math.max(dp[i][1], dp[i - 1][1] + arr[i]); // Case 3:(a) Altering sign and add to previous case 2 if (i >= 2) dp[i][2] = dp[i - 1][1] - arr[i]; // Case 3:(b) Adding current element with previous case 3 if (i >= 3) dp[i][2] = Math.max(dp[i][2], dp[i - 1][2] + arr[i]); // Updating the maximum value of variable ans ans = Math.max(ans, dp[i][0]); ans = Math.max(ans, dp[i][1]); ans = Math.max(ans, dp[i][2]); } // Return the final solution return ans; } let arr = [ -5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6 ]; let n = arr.length; document.write(maxSum(arr, n)); </script> |
61
Time Complexity :
Space Complexity :
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!