Open In App

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

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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 */


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>


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


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


C#




using System;
 
class Program {
    const int N = 5;
 
    // Function to return the maximum sum
    static int GetMaximumSum(int[] a, int n, int x)
    {
        int[, ] dp = new int[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 = 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;
    }
 
    // Driver code
    static void Main()
    {
        int[] a = { -3, 8, -2, 1, -6 };
        int n = a.Length;
        int x = -1;
        // function call
        Console.WriteLine(GetMaximumSum(a, n, x));
    }
}


Javascript




// Function to return the maximum sum
function getMaximumSum(a, n, x) {
    // Initializing the dp array
    let dp = Array.from({ length: n }, () => Array(3).fill(0));
    for (let 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 (let i = n - 2; i >= 0; i--) {
        for (let j = 0; j < 3; j++) {
            // to track the answer in each condition
            let 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
    let maxi = 0;
    for (let i = 0; i < n; i++) {
        maxi = Math.max(maxi, dp[i][0]);
    }
 
    // return final answer
    return maxi;
}
 
// Driver code
let a = [-3, 8, -2, 1, -6];
let n = a.length;
let x = -1;
 
// function call
console.log(getMaximumSum(a, n, x));


Output: 

15

 

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



Last Updated : 17 Jul, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads