Open In App

Maximum Subarray Sum after inverting at most two elements

Last Updated : 03 Jun, 2021
Improve
Improve
Like Article
Like
Save
Share
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)
 



Similar Reads

Maximize subarray sum by inverting sign of elements of any subarray at most twice
Given an array A of size n, find the maximum subarray sum after applying the given operation at most two times. In one operation, choose any two indices i and j and invert sign of all the elements from index i to index j, i.e, all positive elements in the range i to j become negative and all negative elements become positive. Examples: Input: A[] =
10 min read
Maximum subarray sum possible after removing at most one subarray
Given an array arr[] consisting of N integers, the task is to find the maximum sum of any subarray possible after removing at most one subarray from the given array. Examples: Input: arr[] = {-1, 5, 2, -1, 6}Output: 13Explanation:The maximum sum can be obtained by selecting the subarray {5, 2, -1, 6} and removing the subarray {-1}. Input: arr[] = {
9 min read
Maximum subarray sum possible after removing at most K array elements
Given an array arr[] of size N and an integer K, the task is to find the maximum subarray sum by removing at most K elements from the array. Examples: Input: arr[] = { -2, 1, 3, -2, 4, -7, 20 }, K = 1 Output: 26 Explanation: Removing arr[5] from the array modifies arr[] to { -2, 1, 3, -2, 4, 20 } Subarray with maximum sum is { 1, 3, -2, 4, 20 }. Th
17 min read
Check if all the elements can be made of same parity by inverting adjacent elements
Given a binary matrix. In a single operation, you are allowed to choose two adjacent elements and invert their parity. The operation can be performed any number of times. Write a program to check if all the elements of the array can be converted into a single parity. Examples: Input: a[] = {1, 0, 1, 1, 0, 1} Output: Yes Invert 2nd and 3rd elements
4 min read
Total distinct pairs from two arrays such that second number can be obtained by inverting bits of first
Given two arrays arr1[] and arr2[], the task is to take an element from first array (say a) and one element from second array (say b). If the number formed by inverting the bits of a is equal to b, then the pair (a, b) is a valid pair. Inversion Of bits example: 11 is written as 1011 in binary. After inverting it's bits, 0100 is obtained which is 4
8 min read
Maximize the subarray sum after multiplying all elements of any subarray with X
Given an array arr[] of N integers and an integer X. We can choose any sub-array and multiply all its element by X. After multiplication, find the sub-array with the maximum sum. The task is to multiply the sub-array in such a way that the final sub-array sum is maximized. Examples: Input: arr[] = { -3, 8, -2, 1, -6 }, X = -1 Output: 15 Choose the
17 min read
Minimize the Array sum by inverting 0 bit K times
Given an array arr[] of size N and an integer K, the task is to invert the 0 bit (unset bit) of any integer of given array total K times, such that the overall sum of arr gets minimized. Examples: Input: arr = {3, 7, 3}, K = 2Output: 21Explanation: Binary representation 3 is 11, and 7 is 111. Since we need to set 2 bits, we can set the lowest unset
8 min read
Maximum subarray sum by flipping signs of at most K array elements
Given an array arr[] of N integers and an integer K, The task is to find the maximum sub-array sum by flipping signs of at most K array elements. Examples: Input: arr[] = {-6, 2, -1, -1000, 2}, k = 2 Output: 1009 We can flip the signs of -6 and -1000, to get maximum subarray sum as 1009 Input: arr[] = {-1, -2, -100, -10}, k = 1 Output: 100 We can o
9 min read
First subarray having sum at least half the maximum sum of any subarray of size K
Given an array arr[] and an integer K, the task is to find the first subarray which has a sum greater than or equal to half of the maximum possible sum from any subarray of size K. Examples: Input: arr[] = {2, 4, 5, 1, 4, 6, 6, 2, 1, 0}, K = 3 Output: 6 2 1 Explanation: The given array has a maximum possible sum from any subarray of size K is 16 fr
9 min read
Find smallest number formed by inverting digits of given number N
Given an integer N, the task is to form a minimum possible positive number (&gt;0) by inverting some digits of N. Inverting for a digit T is defined as subtracting it from 9 that is 9 - T. Note: The final number should not start from zero. Examples: Input:N = 4545Output: 4444Explanation:The minimum possible number is 4444 by subtracting the two 5 (
9 min read