Skip to content
Related Articles
Get the best out of our app
GeeksforGeeks App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Maximize the subarray sum after multiplying all elements of any subarray with X

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

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 sub-array with {-2, 1, -6} and multiply X. 
Now the new array is {-3, 8, 2, -1, 6} whose maximum sub-array sum is 15. 
Input: arr[] = {1, 2, 4, -10}, X = 2 
Output: 14 
 

 

Approach: The problem cannot be solved using a greedy approach. Greedy approach fails in many cases one of them being a[] = { -3, 8, -2, 1, 6 } and x = -1. We will use Dynamic Programming to solve the above problem. Let dp[ind][state], where ind is the current index in the array and there are 3 states. 
 

  • The first state defines that no sub-array has been chosen till index ind to be multiplied with X.
  • The second state defines that the current element at index ind is in the sub-array which is multiplied with X.
  • The third state defines that the sub-array has already been chosen.

Kadane’s algorithm has been used along with DP to get the maximum subarray sum simultaneously. 
Below is the implementation of the above approach: 
 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define N 5
 
// Function to return the maximum sum
int func(int idx, int cur, int a[], int dp[N][3], int n, int x)
{
 
    // Base case
    if (idx == n)
        return 0;
 
    // If already calculated
    if (dp[idx][cur] != -1)
        return dp[idx][cur];
 
    int ans = 0;
 
    // If no elements have been chosen
    if (cur == 0) {
 
        // Do not choose any element and use
        // Kadane's algorithm by taking max
        ans = max(ans, a[idx] + func(idx + 1, 0, a, dp, n, x));
 
        // Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x));
    }
    else if (cur == 1) {
 
        // Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x));
 
        // End the sub-array multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x));
    }
    else
 
        // No more multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x));
 
    // Memoize and return the answer
    return dp[idx][cur] = ans;
}
 
// Function to get the maximum sum
int getMaximumSum(int a[], int n, int x)
{
 
    // Initialize dp with -1
    int dp[n][3];
    memset(dp, -1, sizeof dp);
 
    // Iterate from every position and find the
    // maximum sum which is possible
    int maxi = 0;
    for (int i = 0; i < n; i++)
        maxi = max(maxi, func(i, 0, a, dp, n, x));
 
    return maxi;
}
 
// Driver code
int main()
{
    int a[] = { -3, 8, -2, 1, -6 };
    int n = sizeof(a) / sizeof(a[0]);
    int x = -1;
 
    cout << getMaximumSum(a, n, x);
 
    return 0;
}

Java




// Java implementation of the approach
class GFG
{
 
    static int N = 5;
 
// Function to return the maximum sum
static int func(int idx, int cur, int a[],
                int dp[][], int n, int x)
{
 
    // Base case
    if (idx == n)
    {
        return 0;
    }
 
    // If already calculated
    if (dp[idx][cur] != -1)
    {
        return dp[idx][cur];
    }
 
    int ans = 0;
 
    // If no elements have been chosen
    if (cur == 0)
    {
 
        // Do not choose any element and use
        // Kadane's algorithm by taking max
        ans = Math.max(ans, a[idx] +
                func(idx + 1, 0, a, dp, n, x));
 
        // Choose the sub-array and multiply x
        ans = Math.max(ans, x * a[idx] +
                func(idx + 1, 1, a, dp, n, x));
    }
    else if (cur == 1)
    {
 
        // Choose the sub-array and multiply x
        ans = Math.max(ans, x * a[idx] +
                func(idx + 1, 1, a, dp, n, x));
 
        // End the sub-array multiplication
        ans = Math.max(ans, a[idx] +
                func(idx + 1, 2, a, dp, n, x));
    }
    else // No more multiplication
    {
        ans = Math.max(ans, a[idx] +
                func(idx + 1, 2, a, dp, n, x));
    }
 
    // Memoize and return the answer
    return dp[idx][cur] = ans;
}
 
// Function to get the maximum sum
static int getMaximumSum(int a[], int n, int x)
{
 
    // Initialize dp with -1
    int dp[][] = new int[n][3];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            dp[i][j] = -1;
        }
    }
 
    // Iterate from every position and find the
    // maximum sum which is possible
    int maxi = 0;
    for (int i = 0; i < n; i++)
    {
        maxi = Math.max(maxi, func(i, 0, a, dp, n, x));
    }
 
    return maxi;
}
 
// Driver code
public static void main(String[] args)
{
    int a[] = {-3, 8, -2, 1, -6};
    int n = a.length;
    int x = -1;
    System.out.println(getMaximumSum(a, n, x));
 
}
}
 
// This code has been contributed by 29AjayKumar

Python3




# Python3 implementation of the approach
 
N = 5
 
# Function to return the maximum sum
def func(idx, cur, a, dp, n, x) :
  
 
    # Base case
    if (idx == n) :
        return 0
 
    # If already calculated
    if (dp[idx][cur] != -1):
        return dp[idx][cur]
 
    ans = 0
 
    # If no elements have been chosen
    if (cur == 0) :
 
        # Do not choose any element and use
        # Kadane's algorithm by taking max
        ans = max(ans, a[idx] + func(idx + 1, 0, a, dp, n, x))
 
        # Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x))
      
    elif (cur == 1) :
 
        # Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x))
 
        # End the sub-array multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x))
      
    else :
 
        # No more multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x))
 
    # Memoize and return the answer
    dp[idx][cur] = ans
     
    return dp[idx][cur]
  
 
# Function to get the maximum sum
def getMaximumSum(a, n, x) :
  
 
    # Initialize dp with -1
    dp = [[-1 for i in range(3)] for j in range(n)]
     
 
    # Iterate from every position and find the
    # maximum sum which is possible
    maxi = 0
    for i in range (0, n) :
        maxi = max(maxi, func(i, 0, a, dp, n, x))
 
    return maxi
  
 
# Driver code
 
a =  [ -3, 8, -2, 1, -6 ]  
n = len(a)
x = -1
 
print(getMaximumSum(a, n, x))
 
# This code is contributed by ihritik

C#




// C# implementation of the approach
using System;
 
class GFG
{
 
    static int N = 5;
 
// Function to return the maximum sum
static int func(int idx, int cur, int []a,
                int [,]dp, int n, int x)
{
 
    // Base case
    if (idx == n)
    {
        return 0;
    }
 
    // If already calculated
    if (dp[idx,cur] != -1)
    {
        return dp[idx,cur];
    }
 
    int ans = 0;
 
    // If no elements have been chosen
    if (cur == 0)
    {
 
        // Do not choose any element and use
        // Kadane's algorithm by taking max
        ans = Math.Max(ans, a[idx] +
                func(idx + 1, 0, a, dp, n, x));
 
        // Choose the sub-array and multiply x
        ans = Math.Max(ans, x * a[idx] +
                func(idx + 1, 1, a, dp, n, x));
    }
    else if (cur == 1)
    {
 
        // Choose the sub-array and multiply x
        ans = Math.Max(ans, x * a[idx] +
                func(idx + 1, 1, a, dp, n, x));
 
        // End the sub-array multiplication
        ans = Math.Max(ans, a[idx] +
                func(idx + 1, 2, a, dp, n, x));
    }
    else // No more multiplication
    {
        ans = Math.Max(ans, a[idx] +
                func(idx + 1, 2, a, dp, n, x));
    }
 
    // Memoize and return the answer
    return dp[idx,cur] = ans;
}
 
// Function to get the maximum sum
static int getMaximumSum(int []a, int n, int x)
{
 
    // Initialize dp with -1
    int [,]dp = new int[n,3];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            dp[i,j] = -1;
        }
    }
 
    // Iterate from every position and find the
    // maximum sum which is possible
    int maxi = 0;
    for (int i = 0; i < n; i++)
    {
        maxi = Math.Max(maxi, func(i, 0, a, dp, n, x));
    }
 
    return maxi;
}
 
// Driver code
public static void Main(String[] args)
{
    int []a = {-3, 8, -2, 1, -6};
    int n = a.Length;
    int x = -1;
    Console.WriteLine(getMaximumSum(a, n, x));
 
}
}
 
/* This code contributed by PrinciRaj1992 */

PHP




<?php
// PHP implementation of the approach
 
$N = 5;
 
// Function to return the maximum sum
function func($idx, $cur, $a, $dp, $n, $x)
{
 
    // Base case
    if ($idx == $n)
        return 0;
 
    // If already calculated
    if ($dp[$idx][$cur] != -1)
        return $dp[$idx][$cur];
 
    $ans = 0;
 
    // If no elements have been chosen
    if ($cur == 0)
    {
 
        // Do not choose any element and use
        // Kadane's algorithm by taking max
        $ans = max($ans, $a[$idx] +
                func($idx + 1, 0, $a, $dp, $n, $x));
 
        // Choose the sub-array and multiply x
        $ans = max($ans, $x * $a[$idx] +
                func($idx + 1, 1, $a, $dp, $n, $x));
    }
    else if ($cur == 1)
    {
 
        // Choose the sub-array and multiply x
        $ans = max($ans, $x * $a[$idx] +
                func($idx + 1, 1, $a, $dp, $n, $x));
 
        // End the sub-array multiplication
        $ans = max($ans, $a[$idx] +
                func($idx + 1, 2, $a, $dp, $n, $x));
    }
    else
 
        // No more multiplication
        $ans = max($ans, $a[$idx] +
                func($idx + 1, 2, $a, $dp,$n, $x));
 
    // Memoize and return the answer
    return $dp[$idx][$cur] = $ans;
}
 
// Function to get the maximum sum
function getMaximumSum($a, $n, $x)
{
 
    // Initialize dp with -1
    $dp = array(array()) ;
     
    for($i = 0; $i < $n; $i++)
    {
        for($j = 0; $j < 3; $j++)
        {
            $dp[$i][$j] = -1;
        }
    }
 
    // Iterate from every position and find the
    // maximum sum which is possible
    $maxi = 0;
    for ($i = 0; $i < $n; $i++)
        $maxi = max($maxi, func($i, 0, $a, $dp, $n, $x));
 
    return $maxi;
}
 
    // Driver code
    $a = array( -3, 8, -2, 1, -6 );
    $n = count($a) ;
    $x = -1;
 
    echo getMaximumSum($a, $n, $x);
     
    // This code is contributed by Ryuga
?>

Javascript




<script>
 
// JavaScript implementation of the approach   
var N = 5;
 
    // Function to return the maximum sum
    function func(idx , cur , a , dp , n , x) {
 
        // Base case
        if (idx == n) {
            return 0;
        }
 
        // If already calculated
        if (dp[idx][cur] != -1) {
            return dp[idx][cur];
        }
 
        var ans = 0;
 
        // If no elements have been chosen
        if (cur == 0) {
 
            // Do not choose any element and use
            // Kadane's algorithm by taking max
            ans = Math.max(ans, a[idx] +
            func(idx + 1, 0, a, dp, n, x));
 
            // Choose the sub-array and multiply x
            ans = Math.max(ans, x * a[idx] +
            func(idx + 1, 1, a, dp, n, x));
        } else if (cur == 1) {
 
            // Choose the sub-array and multiply x
            ans = Math.max(ans, x * a[idx] +
            func(idx + 1, 1, a, dp, n, x));
 
            // End the sub-array multiplication
            ans = Math.max(ans, a[idx] +
            func(idx + 1, 2, a, dp, n, x));
        } else // No more multiplication
        {
            ans = Math.max(ans, a[idx] +
            func(idx + 1, 2, a, dp, n, x));
        }
 
        // Memoize and return the answer
        return dp[idx][cur] = ans;
    }
 
    // Function to get the maximum sum
    function getMaximumSum(a , n , x) {
 
        // Initialize dp with -1
        var dp = Array(n).fill().map(()=>Array(3).fill(0));
        for (i = 0; i < n; i++) {
            for (j = 0; j < 3; j++) {
                dp[i][j] = -1;
            }
        }
 
        // Iterate from every position and find the
        // maximum sum which is possible
        var maxi = 0;
        for (i = 0; i < n; i++) {
            maxi = Math.max(maxi, func(i, 0, a, dp, n, x));
        }
 
        return maxi;
    }
 
    // Driver code
     
        var a = [ -3, 8, -2, 1, -6 ];
        var n = a.length;
        var x = -1;
        document.write(getMaximumSum(a, n, x));
 
// This code contributed by Rajput-Ji
 
</script>

Output: 

15

 

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

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

  • Create a DP to store the solution of the subproblems.
  • Initialize the DP with base cases
  • Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP.
  • Create a variable ans to keep track of values of DP in each condition.
  • After iteration from loop create a variable maxi to store the maximum sum and update it by iterate over Dp.
  • Return the final solution stored in maxi.

Implementation :
 

C++




#include <bits/stdc++.h>
using namespace std;
#define N 5
 
// Function to return the maximum sum
int getMaximumSum(int a[], int n, int x)
{
    int dp[n][3];
 
    // Initializing the dp array
    for(int i=0; i<n; i++){
        dp[i][0] = a[i];
        dp[i][1] = a[i]*x;
        dp[i][2] = a[i];
    }
 
    // Applying the recurrence relation
    for(int i=n-2; i>=0; i--){
        for(int j=0; j<3; j++){
           
              // to track the answer in each condition
            int ans = 0;
            if(j==0){
                ans = max(dp[i][j], dp[i+1][j]+a[i]);
                ans = max(ans, dp[i+1][j+1]+x*a[i]);
            }
            else if(j==1){
                ans = max(dp[i][j], dp[i+1][j]+x*a[i]);
                ans = max(ans, dp[i+1][j+1]+a[i]);
            }
            else{
                ans = max(dp[i][j], dp[i+1][j]+a[i]);
            }
           
              // update DP
            dp[i][j] = ans;
        }
    }
 
    // Finding the maximum sum from dp array
    int maxi = 0;
    for (int i = 0; i < n; i++)
        maxi = max(maxi, dp[i][0]);
     
      // return final answer
    return maxi;
}
 
// Driver code
int main()
{
    int a[] = { -3, 8, -2, 1, -6 };
    int n = sizeof(a) / sizeof(a[0]);
    int x = -1;
    // function call
    cout << getMaximumSum(a, n, x);
 
    return 0;
}

Java




import java.util.*;
 
public class Main {
 
  public static int getMaximumSum(int[] a, int n, int x)
  {
 
    // Initializing the dp array
    int[][] dp = new int[n][3];
    for (int i = 0; i < n; i++) {
      dp[i][0] = a[i];
      dp[i][1] = a[i] * x;
      dp[i][2] = a[i];
    }
 
    // Applying the recurrence relation
    for (int i = n - 2; i >= 0; i--) {
      for (int j = 0; j < 3; j++) {
 
        // to track the answer in each condition
        int ans = 0;
        if (j == 0) {
          ans = Math.max(dp[i][j],
                         dp[i + 1][j] + a[i]);
          ans = Math.max(ans, dp[i + 1][j + 1]
                         + x * a[i]);
        }
        else if (j == 1) {
          ans = Math.max(dp[i][j],
                         dp[i + 1][j] + x * a[i]);
          ans = Math.max(ans,
                         dp[i + 1][j + 1] + a[i]);
        }
        else {
          ans = Math.max(dp[i][j],
                         dp[i + 1][j] + a[i]);
        }
 
        // update DP
        dp[i][j] = ans;
      }
    }
 
    // Finding the maximum sum from dp array
    int maxi = 0;
    for (int i = 0; i < n; i++) {
      maxi = Math.max(maxi, dp[i][0]);
    }
 
    // return final answer
    return maxi;
  }
 
  public static void main(String[] args)
  {
    int[] a = { -3, 8, -2, 1, -6 };
    int n = a.length;
    int x = -1;
 
    // function call
    System.out.println(getMaximumSum(a, n, x));
  }
}
 
// This code is contributed by user_dtewbxkn77n

Python3




# Function to return the maximum sum
def getMaximumSum(a, n, x):
   
    # Initializing the dp array
    dp = [[0 for j in range(3)] for i in range(n)]
    for i in range(n):
        dp[i][0] = a[i]
        dp[i][1] = a[i] * x
        dp[i][2] = a[i]
 
    # Applying the recurrence relation
    for i in range(n-2, -1, -1):
        for j in range(3):
           
            # to track the answer in each condition
            ans = 0
            if j == 0:
                ans = max(dp[i][j], dp[i+1][j]+a[i])
                ans = max(ans, dp[i+1][j+1]+x*a[i])
            elif j == 1:
                ans = max(dp[i][j], dp[i+1][j]+x*a[i])
                ans = max(ans, dp[i+1][j+1]+a[i])
            else:
                ans = max(dp[i][j], dp[i+1][j]+a[i])
             
            # update DP
            dp[i][j] = ans
 
    # Finding the maximum sum from dp array
    maxi = 0
    for i in range(n):
        maxi = max(maxi, dp[i][0])
 
    # return final answer
    return maxi
 
# Driver code
if __name__ == '__main__':
    a = [-3, 8, -2, 1, -6]
    n = len(a)
    x = -1
     
    # function call
    print(getMaximumSum(a, n, x))

Output: 

15

 

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


My Personal Notes arrow_drop_up
Last Updated : 20 Apr, 2023
Like Article
Save Article
Similar Reads
Related Tutorials