Given an array that contains both positive and negative integers, find the product of the maximum product subarray. Expected Time complexity is O(n) and only O(1) extra space can be used. The maximum product can be positive, negative or zero.
Examples:
Input : arr[] = {-2, -3, 0, -2, -40}
Output : 80
Subarray : arr[3..4] i.e.{-2, -40}
Input : arr[] = {0, -4, 0, -2}
Output : 0
We have discussed this problem in Maximum Product Subarray, but there is a restriction that result can only be positive. For the maximum product to be negative or zero, the values of variable maxval (maximum product up to current element) and minval (minimum product up to current element), has to be updated as follows:
- When arr[i] is positive: As maxval is maximum possible value, simply multiply arr[i] with maxval to obtain new maxval. minval is minimum possible negative product. If its previous value is negative then simply multiply it with arr[i]. If its value is 1 keep it as 1.
- When arr[i] is 0: Consider the test case : arr[] = {0, -4, 0, -2}. The maximum product is 0 in this case. To account for this case in our algo, update maxval with 0 instead of 1 whenever arr[i] is zero. The product of any number with zero is zero. Consider another test case, arr[] = {0, 1 ,2}.
If maxval remains zero after current iteration (according to the step described above) and the next element is positive then the result will be zero and not the positive element. To consider that at the end of each iteration check if maxval is zero or not.
If it is zero set it equal to 1. Update minval with 1 as subarray product with zero as element in it will be zero, which results in loss of minimum possible value. So exclude this zero from subarray by setting minval to 1, i.e., restarting product calculation. - When arr[i] is negative: new value of maxval is previous minval*arr[i] and new value of minval is previous maxval*arr[i]. Before updating maxval, store its previous value in prevMax to be used to update minval.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int findMaxProduct( int arr[], int n)
{
int i;
int ans = INT_MIN;
int maxval = 1;
int minval = 1;
int prevMax;
for (i = 0; i < n; i++) {
if (arr[i] > 0) {
maxval = maxval * arr[i];
minval = min(1, minval * arr[i]);
}
else if (arr[i] == 0) {
minval = 1;
maxval = 0;
}
else if (arr[i] < 0) {
prevMax = maxval;
maxval = minval * arr[i];
minval = prevMax * arr[i];
}
ans = max(ans, maxval);
if (maxval <= 0) {
maxval = 1;
}
}
return ans;
}
int main()
{
int arr[] = { 0, -4, 0, -2 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << findMaxProduct(arr, n);
return 0;
}
|
Java
class GFG{
static int findMaxProduct( int arr[], int n)
{
int i;
int ans = Integer.MIN_VALUE;
int maxval = 1 ;
int minval = 1 ;
int prevMax;
for (i = 0 ; i < n; i++) {
if (arr[i] > 0 ) {
maxval = maxval * arr[i];
minval = Math.min( 1 , minval * arr[i]);
}
else if (arr[i] == 0 ) {
minval = 1 ;
maxval = 0 ;
}
else if (arr[i] < 0 ) {
prevMax = maxval;
maxval = minval * arr[i];
minval = prevMax * arr[i];
}
ans = Math.max(ans, maxval);
if (maxval <= 0 ) {
maxval = 1 ;
}
}
return ans;
}
public static void main(String[] args) {
int arr[] = { 0 , - 4 , 0 , - 2 };
int n = arr.length;
System.out.println(findMaxProduct(arr, n));
}
}
|
Python3
def findMaxProduct(arr, n):
ans = - float ( 'inf' )
maxval = 1
minval = 1
for i in range ( 0 , n):
if arr[i] > 0 :
maxval = maxval * arr[i]
minval = min ( 1 , minval * arr[i])
elif arr[i] = = 0 :
minval = 1
maxval = 0
elif arr[i] < 0 :
prevMax = maxval
maxval = minval * arr[i]
minval = prevMax * arr[i]
ans = max (ans, maxval)
if maxval < = 0 :
maxval = 1
return ans
if __name__ = = "__main__" :
arr = [ 0 , - 4 , 0 , - 2 ]
n = len (arr)
print (findMaxProduct(arr, n))
|
C#
using System;
class GFG
{
static int findMaxProduct( int [] arr, int n)
{
int i;
int ans = Int32.MinValue;
int maxval = 1;
int minval = 1;
int prevMax;
for (i = 0; i < n; i++)
{
if (arr[i] > 0)
{
maxval = maxval * arr[i];
minval = Math.Min(1, minval * arr[i]);
}
else if (arr[i] == 0)
{
minval = 1;
maxval = 0;
}
else if (arr[i] < 0)
{
prevMax = maxval;
maxval = minval * arr[i];
minval = prevMax * arr[i];
}
ans = Math.Max(ans, maxval);
if (maxval <= 0)
{
maxval = 1;
}
}
return ans;
}
public static void Main()
{
int [] arr = { 0, -4, 0, -2 };
int n = arr.Length;
Console.WriteLine(findMaxProduct(arr, n));
}
}
|
PHP
<?php
function findMaxProduct(& $arr , $n )
{
$ans = 0;
$maxval = 1;
$minval = 1;
for ( $i = 0; $i < $n ; $i ++)
{
if ( $arr [ $i ] > 0)
{
$maxval = $maxval * $arr [i];
$minval = min(1, $minval * $arr [ $i ]);
}
else if ( $arr [ $i ] == 0)
{
$minval = 1;
$maxval = 0;
}
else if ( $arr [ $i ] < 0)
{
$prevMax = $maxval ;
$maxval = $minval * $arr [ $i ];
$minval = $prevMax * $arr [ $i ];
}
$ans = max( $ans , $maxval );
if ( $maxval <= 0)
{
$maxval = 1;
}
}
return $ans ;
}
$arr = array ( 0, -4, 0, -2 );
$n = sizeof( $arr );
echo findMaxProduct( $arr , $n );
?>
|
Javascript
<script>
function findMaxProduct(arr, n)
{
let i;
let ans = -1;
let maxval = 1;
let minval = 1;
let prevMax;
for (i = 0; i < n; i++) {
if (arr[i] > 0) {
maxval = maxval * arr[i];
minval = Math.min(1, minval * arr[i]);
}
else if (arr[i] == 0) {
minval = 1;
maxval = 0;
}
else if (arr[i] < 0) {
prevMax = maxval;
maxval = minval * arr[i];
minval = prevMax * arr[i];
}
ans = Math.max(ans, maxval);
if (maxval <= 0) {
maxval = 1;
}
}
return ans;
}
let arr = [ 0, -4, 0, -2 ];
let n = arr.length;
document.write(findMaxProduct(arr, n));
</script>
|
Complexity Analysis:
- Time Complexity: O(n)
- Auxiliary Space: O(1)