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.
Examples :
Input: arr[] = {6, -3, -10, 0, 2}
Output: 180 // The subarray is {6, -3, -10}
Input: arr[] = {-1, -3, -10, 0, 60}
Output: 60 // The subarray is {60}
Input: arr[] = {-1, -2, -3, 4}
Output: 24 // The subarray is {-2, -3, 4}
Input: arr[] = {-10}
Output: 0 // An empty array is also subarray
// and product of empty subarray is
// considered as 0.
We have discussed a solution of this problem here.
In this post an interesting solution is discussed. The idea is based on the fact that overall maximum product is maximum of following two:
- Maximum product in left to right traversal.
- Maximum product in right to left traversal
For example, consider the above third sample input {-1, -2, -3, 4}. If we traverse the array only in forward direction (considering -1 as part of output), maximum product will be 2. If we traverse the array in backward direction (considering 4 as part of output), maximum product will be 24 i.e; { -2, -3, 4}.
One important thing is to handle 0’s. We need to compute fresh forward (or backward) sum whenever we see 0.
Below is the implementation of above idea :
C++
#include<bits/stdc++.h>
using namespace std;
int max_product( int arr[], int n)
{
int max_fwd = INT_MIN, max_bkd = INT_MIN;
int max_till_now = 1;
bool isZero= false ;
for ( int i=0; i<n; i++)
{
max_till_now = max_till_now*arr[i];
if (max_till_now == 0)
{
isZero= true ;
max_till_now = 1;
continue ;
}
if (max_fwd < max_till_now)
max_fwd = max_till_now;
}
max_till_now = 1;
for ( int i=n-1; i>=0; i--)
{
max_till_now = max_till_now * arr[i];
if (max_till_now == 0)
{
isZero= true ;
max_till_now = 1;
continue ;
}
if (max_bkd < max_till_now)
max_bkd = max_till_now;
}
int res = max(max_fwd, max_bkd);
if (isZero)
return max(res, 0);
return res;
}
int main()
{
int arr[] = {-1, -2, -3, 4};
int n = sizeof (arr)/ sizeof (arr[0]);
cout << max_product(arr, n) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int max_product( int arr[], int n)
{
int max_fwd = Integer.MIN_VALUE,
max_bkd = Integer.MIN_VALUE;
boolean isZero= false ;
int max_till_now = 1 ;
for ( int i = 0 ; i < n; i++)
{
max_till_now = max_till_now * arr[i];
if (max_till_now == 0 )
{
isZero= true ;
max_till_now = 1 ;
continue ;
}
if (max_fwd < max_till_now)
max_fwd = max_till_now;
}
max_till_now = 1 ;
for ( int i = n - 1 ; i >= 0 ; i--)
{
max_till_now = max_till_now * arr[i];
if (max_till_now == 0 )
{
isZero= true ;
max_till_now = 1 ;
continue ;
}
if (max_bkd < max_till_now)
max_bkd = max_till_now;
}
int res = Math. max(max_fwd, max_bkd);
if (isZero)
return Math.max(res, 0 );
return res;
}
public static void main (String[] args)
{
int arr[] = {- 1 , - 2 , - 3 , 4 };
int n = arr.length;
System.out.println( max_product(arr, n) );
}
}
|
Python3
import sys
def max_product(arr, n):
max_fwd = - sys.maxsize - 1
max_bkd = - sys.maxsize - 1
isZero = False ;
max_till_now = 1
for i in range (n):
max_till_now = max_till_now * arr[i]
if (max_till_now = = 0 ):
isZero = True
max_till_now = 1 ;
continue
if (max_fwd < max_till_now):
max_fwd = max_till_now
max_till_now = 1
for i in range (n - 1 , - 1 , - 1 ):
max_till_now = max_till_now * arr[i]
if (max_till_now = = 0 ):
isZero = True
max_till_now = 1
continue
if (max_bkd < max_till_now) :
max_bkd = max_till_now
res = max (max_fwd, max_bkd)
if isZero = = True :
return max (res, 0 )
return res
arr = [ - 1 , - 2 , - 3 , 4 ]
n = len (arr)
print (max_product(arr, n))
|
C#
using System;
class GFG {
static int max_product( int []arr, int n)
{
int max_fwd = int .MinValue,
max_bkd = int .MinValue;
int max_till_now = 1;
for ( int i = 0; i < n; i++)
{
max_till_now = max_till_now * arr[i];
if (max_till_now == 0)
{
max_till_now = 1;
continue ;
}
if (max_fwd < max_till_now)
max_fwd = max_till_now;
}
max_till_now = 1;
for ( int i = n - 1; i >= 0; i--)
{
max_till_now = max_till_now * arr[i];
if (max_till_now == 0)
{
max_till_now = 1;
continue ;
}
if (max_bkd < max_till_now)
max_bkd = max_till_now;
}
int res = Math. Max(max_fwd, max_bkd);
return Math.Max(res, 0);
}
public static void Main ()
{
int []arr = {-1, -2, -3, 4};
int n = arr.Length;
Console.Write( max_product(arr, n) );
}
}
|
PHP
<?php
function max_product( $arr , $n )
{
$max_fwd = PHP_INT_MIN;
$max_bkd = PHP_INT_MIN;
$max_till_now = 1;
for ( $i = 0; $i < $n ; $i ++)
{
$max_till_now = $max_till_now * $arr [ $i ];
if ( $max_till_now == 0)
{
$max_till_now = 1;
continue ;
}
if ( $max_fwd < $max_till_now )
$max_fwd = $max_till_now ;
}
$max_till_now = 1;
for ( $i = $n - 1; $i >= 0; $i --)
{
$max_till_now = $max_till_now * $arr [ $i ];
if ( $max_till_now == 0)
{
$max_till_now = 1;
continue ;
}
if ( $max_bkd < $max_till_now )
$max_bkd = $max_till_now ;
}
$res = max( $max_fwd , $max_bkd );
return max( $res , 0);
}
$arr = array (-1, -2, -3, 4);
$n = count ( $arr );
echo max_product( $arr , $n );
?>
|
Javascript
<script>
function max_product(arr, n)
{
let max_fwd = Number.MIN_VALUE,
max_bkd = Number.MIN_VALUE;
let max_till_now = 1;
for (let i = 0; i < n; i++)
{
max_till_now = max_till_now * arr[i];
if (max_till_now == 0)
{
max_till_now = 1;
continue ;
}
if (max_fwd < max_till_now)
max_fwd = max_till_now;
}
max_till_now = 1;
for (let i = n - 1; i >= 0; i--)
{
max_till_now = max_till_now * arr[i];
if (max_till_now == 0)
{
max_till_now = 1;
continue ;
}
if (max_bkd < max_till_now)
max_bkd = max_till_now;
}
let res = Math.max(max_fwd, max_bkd);
return Math.max(res, 0);
}
let arr = [-1, -2, -3, 4];
let n = arr.length;
document.write(max_product(arr, n) );
</script>
|
Time Complexity : O(n)
Auxiliary Space : O(1)
Note that the above solution requires two traversals of an array while the previous solution requires only one traversal.
This article is contributed by Shashank Mishra (Gullu). If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.