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++ 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 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 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# 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 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 ?> |
<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> |
Output:
61
Time Complexity :
Space Complexity :