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

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
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));
  
    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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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)); 
  
    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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach
using System;
  
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));
  
    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

chevron_right


Output:

100

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



My Personal Notes arrow_drop_up

Striver(underscore)79 at Codechef and codeforces D

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.



Improved By : AnkitRai01, Mithun Kumar