Skip to content
Related Articles

Related Articles

Maximum subarray sum by flipping signs of at most K array elements
  • Difficulty Level : Hard
  • Last Updated : 25 Jan, 2021

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 only flip the sign of -100 to get 100 

Input: {1, 2, 100, 10}, k = 1 
Output: 113 
We do not need to flip any elements 



Approach: The problem can be solved using Dynamic Programming. Let dp[i][j] be the maximum sub-array sum from index i with j flips. A recursive function can be written in order to solve the problem and we can memoize it to avoid multiple function calls. The recursive DP function (findSubarraySum(ind, flips)) will be called from every index with number of initial flips as 0.

ans = max(0, a[ind] + findSubarraySum(ind + 1, flips, n, a, k)) 
ans = max(ans, -a[ind] + findSubarraySum(ind + 1, flips + 1, n, a, k)) 
If the value is negative we are replacing it by 0, similarly as we do in Kadane’s algorithm. 
 

The recursive function will have two states, one will be if we flip the i-th index. The second one if we don’t flip the i-th index. The base cases being if the ind==n, when we have a completed a traversal till last index. We can use memoization in order to store the results which can be used later to avoid multiple same function calls. The maximum of all dp[i][0] will be our answer.

Below is the implementation of the above approach: 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define right 2
#define left 4
int dp[left][right];
 
// Function to find the maximum subarray sum with flips
// starting from index i
int findSubarraySum(int ind, int flips, int n, int a[],
                    int k)
{
 
    // If the number of flips have exceeded
    if (flips > k)
        return -1e9;
 
    // Complete traversal
    if (ind == n)
        return 0;
 
    // If the state has previously been visited
    if (dp[ind][flips] != -1)
        return dp[ind][flips];
 
    // Initially
    int ans = 0;
 
    // Use Kadane's algorithm and call two states
    ans = max(
        0,
        a[ind] + findSubarraySum(ind + 1, flips, n, a, k));
    ans = max(ans, -a[ind]
                       + findSubarraySum(ind + 1, flips + 1,
                                         n, a, k));
 
    // Memoize the answer and return it
    return dp[ind][flips] = ans;
}
 
// Utility function to call flips from index and
// return the answer
int findMaxSubarraySum(int a[], int n, int k)
{
    // Create DP array
    // int dp[n][k+1];
    memset(dp, -1, sizeof(dp));
 
    int ans = -1e9;
 
    // Iterate and call recurive function
    // from every index to get the maximum subarray sum
    for (int i = 0; i < n; i++)
        ans = max(ans, findSubarraySum(i, 0, n, a, k));
 
    // corner case
    if (ans == 0 && k == 0)
        return *max_element(a, a + n);
 
    return ans;
}
 
// Driver Code
int main()
{
    int a[] = { -1, -2, -100, -10 };
    int n = sizeof(a) / sizeof(a[0]);
    int k = 1;
 
    cout << findMaxSubarraySum(a, n, k);
 
    return 0;
}

Java




// Java implementation of the approach
import java.util.Arrays;
class GFG {
 
    static int right = 2;
    static int left = 4;
    static int[][] dp = new int[left][right];
 
    // Function to find the maximum subarray sum with flips
    // starting from index i
    static int findSubarraySum(int ind, int flips, int n,
                               int[] a, int k)
    {
 
        // If the number of flips have exceeded
        if (flips > k)
            return (int)(-1e9);
 
        // Complete traversal
        if (ind == n)
            return 0;
 
        // If the state has previously been visited
        if (dp[ind][flips] != -1)
            return dp[ind][flips];
 
        // Initially
        int ans = 0;
 
        // Use Kadane's algorithm and call two states
        ans = Math.max(0, a[ind]
                              + findSubarraySum(
                                  ind + 1, flips, n, a, k));
        ans = Math.max(ans, -a[ind]
                                + findSubarraySum(ind + 1,
                                                  flips + 1,
                                                  n, a, k));
 
        // Memoize the answer and return it
        return dp[ind][flips] = ans;
    }
 
    // Utility function to call flips from index and
    // return the answer
    static int findMaxSubarraySum(int[] a, int n, int k)
    {
        // Create DP array
        // int dp[n,k+1];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < k + 1; j++)
                dp[i][j] = -1;
 
        int ans = (int)(-1e9);
 
        // Iterate and call recurive function
        // from every index to get the maximum subarray sum
        for (int i = 0; i < n; i++)
            ans = Math.max(ans,
                           findSubarraySum(i, 0, n, a, k));
 
        // corner case
        if (ans == 0 && k == 0)
            return Arrays.stream(a).max().getAsInt();
 
        return ans;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int[] a = { -1, -2, -100, -10 };
        int n = a.length;
        int k = 1;
 
        System.out.println(findMaxSubarraySum(a, n, k));
    }
}
 
// This code is contributed by mits

Python3




# Python3 implementation of the approach
import numpy as np
 
right = 3;
left = 6;
 
dp = np.ones((left, right))
dp = -1 * dp
 
# Function to find the maximum
# subarray sum with flips starting
# from index i
def findSubarraySum(ind, flips, n, a, k) :
 
    # If the number of flips
    # have exceeded
    if (flips > k) :
        return -1e9;
 
    # Complete traversal
    if (ind == n) :
        return 0;
 
    # If the state has previously
    # been visited
    if (dp[ind][flips] != -1) :
        return dp[ind][flips];
     
    # Initially
    ans = 0;
 
    # Use Kadane's algorithm and
    # call two states
    ans = max(0, a[ind] +
              findSubarraySum(ind + 1,
                              flips, n, a, k));
    ans = max(ans, -a[ind] +
              findSubarraySum(ind + 1, flips + 1,
                                       n, a, k));
 
    # Memoize the answer and return it
    dp[ind][flips] = ans;
     
    return dp[ind][flips] ;
 
# Utility function to call flips
# from index and return the answer
def findMaxSubarraySum(a, n, k) :
 
    ans = -1e9;
     
    # Iterate and call recurive
    # function from every index to
    # get the maximum subarray sum
    for i in range(n) :
        ans = max(ans, findSubarraySum(i, 0, n, a, k));
     
    # corner casae
    if ans == 0 and k == 0:
      return max(a);
 
    return ans;
 
# Driver Code
if __name__ == "__main__" :
 
    a = [-1, -2, -100, -10];
    n = len(a) ;
    k = 1;
 
    print(findMaxSubarraySum(a, n, k));
     
# This code is contributed by Ryuga

C#




// C# implementation of the approach
using System;
using System.Linq;
 
class GFG {
 
    static int right = 2;
    static int left = 4;
    static int[, ] dp = new int[left + 1, right + 1];
 
    // Function to find the maximum subarray sum
    // with flips starting from index i
    static int findSubarraySum(int ind, int flips, int n,
                               int[] a, int k)
    {
 
        // If the number of flips have exceeded
        if (flips > k)
            return -(int)1e9;
 
        // Complete traversal
        if (ind == n)
            return 0;
 
        // If the state has previously been visited
        if (dp[ind, flips] != -1)
            return dp[ind, flips];
 
        // Initially
        int ans = 0;
 
        // Use Kadane's algorithm and call two states
        ans = Math.Max(0, a[ind]
                              + findSubarraySum(
                                  ind + 1, flips, n, a, k));
        ans = Math.Max(ans, -a[ind]
                                + findSubarraySum(ind + 1,
                                                  flips + 1,
                                                  n, a, k));
 
        // Memoize the answer and return it
        return dp[ind, flips] = ans;
    }
 
    // Utility function to call flips from
    // index and return the answer
    static int findMaxSubarraySum(int[] a, int n, int k)
    {
        // Create DP array
        // int dp[n][k+1];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < k + 1; j++)
                dp[i, j] = -1;
 
        int ans = -(int)1e9;
 
        // Iterate and call recurive function
        // from every index to get the maximum subarray sum
        for (int i = 0; i < n; i++)
            ans = Math.Max(ans,
                           findSubarraySum(i, 0, n, a, k));
 
        // corner case
        if (ans == 0 && k == 0)
            return a.Max();
 
        return ans;
    }
 
    // Driver Code
    static void Main()
    {
        int[] a = { -1, -2, -100, -10 };
        int n = a.Length;
        int k = 1;
 
        Console.WriteLine(findMaxSubarraySum(a, n, k));
    }
}
 
// This code is contributed by mits
Output
100

Time Complexity: O(N * K) 
Auxiliary Space: O(N * K)
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  Get hold of all the important mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live and Geeks Classes Live USA

My Personal Notes arrow_drop_up
Recommended Articles
Page :