Open In App

Maximum Subarray Sum after inverting at most two elements

Last Updated : 03 Jun, 2021
Comments
Improve
Suggest changes
Like Article
Like
Report

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)  
 


Next Article

Similar Reads