# Maximum Product Subarray

Problem:

Given an integer array `nums`

, find a contiguous non-empty subarray within the array that has the largest product, and return *the product*.

It is **guaranteed** that the answer will fit in a **32-bit** integer.

A **subarray** is a contiguous subsequence of the array.

**Example 1:**

**Input:** nums = [2,3,-2,4]

**Output:** 6

**Explanation:** [2,3] has the largest product 6.

**Example 2:**

**Input:** nums = [-2,0,-1]

**Output:** 0

**Explanation:** The result cannot be 2, because [-2,-1] is not a subarray.

Approach 1 :

Brute force

Generate all subarray and return max product among them

def maxProduct(self, nums: List[int]) -> int:

max_=-1*float('inf')

for i in range(len(nums)):

prod=1

for j in range(i,len(nums)):

prod*=nums[j]

if(max_<prod):

max_=prod

return(max_)

Time :O(n²)

Space: O(1)

Approach 2:

Optimized solution.

In this we find the maximum and minimum ending at the current index. This is because the element at a position can be negative , positive and also a zero. We know that if a value at an index is negative, then to get maximum we need the minimum till previous index position, and to get minimum , we need maximum till the previous index and vice versa for a positive value at an index, said that , in each iteration we store the global maximum into a variable ‘global_’

`def maxProduct(self, nums):`

global_,max_,min_=nums[0],nums[0],nums[0]

i=1

while(i<len(nums)):

prev_max=max_

max_=max(nums[i],max_*nums[i],min_*nums[i])

min_=min(nums[i],prev_max*nums[i],min_*nums[i])

global_=max(global_,max_)

i+=1

return global_

Time :O(n)

Space: O(1)

Approach 3:

Two pointer solution

The reason for using two pointer in over here is for the reason that, the final answer is subarray that either start from left of the array or from right. So we iterate through the array and constantly calculate the product of contiguous terms from left and right and also store the maximum among them to a variable and return the same . But the edge case here is the value zero . If zero is encountered while in any direction, then if this method is followed as such then all the future product will be zero in that direction .Therefore we reset the the product in that direction to 1 ,so that doesn’t alter the actual answer.

`n=len(nums)`

left,right=1,1

global_max=-1*float('inf')

for i in range(n):

if(left==0):

left=1

if(right==0):

right=1

left*=nums[i]

right=nums[n-1-i]

global_max=max(global_max,left,right)

return global_max