Maximum Subarray Sum after inverting at most two elements

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:

  1. (Maximum sub-array sum) by altering sign of at most 0 element.
  2. (Maximum sub-array sum) by altering sign of at most 1 element.
  3. (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
    1. We alter the sign of current element and then add it to 0 or previous case 1 value. we store whichever is larger.
    2. 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
    1. We alter the sign of current element and add it to previous case 2 value.
    2. 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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


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#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?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
?>

chevron_right


Output:

61

Time Complexity : O(N)
Space Complexity : O(3*N+N) = O(N)



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.