Skip to content
Related Articles

Related Articles

Maximum Subarray Sum after inverting at most two elements

Improve Article
Save Article
  • Difficulty Level : Hard
  • Last Updated : 03 Jun, 2021
Improve Article
Save Article

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




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

Output: 

61

 

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


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!