Reputation: 469
I am trying to solve the Maximum Product Subarray problem from leetcode.
The problem description is: Given an integer array, find the contiguous subarray within the array containing at least one number which has the largest product.
Example: Input: [2,3,-2,4], Output: 6
To solve this I am using the following logic: let f(p,n) output the correct result until index n of the array where the result is p. So the recurrence is:
f(p,n) = p // if(n=a.length)
f(p,n) = max( p, f(p*a[n], n+1), f(a[n], n+1) ) // otherwise
This works for regular recursion (code below).
private int f(int[] a, int p, int n) {
if(n==a.length)
return p;
else
return max(p, f(a, p*a[n], n+1), f(a, a[n], n+1));
}
However I am having trouble converting it to top-down dynamic programming. The approach I have been using to convert a recursive program into one that uses top-down DP is:
This is a general approach that I have been using and it has worked for most of the dp problems I have done however it does not work for this problem.
The (incorrect) code using this approach is shown below:
private int f(int[] a, int p, int n, int[] dp) {
if(dp[n]!=0)
return dp[n];
if(n==a.length)
dp[n] = p;
else
dp[n] = max(p, f_m(a, p*a[n], n+1, dp), f_m(a, a[n], n+1, dp));
return dp[n];
}
I call the functions from the main function as follows:
// int x = f(a, a[0], 1, dp); - for incorrect top-down dp attempt
// int x = f(a, a[0], 1); - for regular recursion
An example where it does not work is: [3,-1,4]. Here it incorrectly outputs 3 instead of 4.
From what I understand, the problem is because both subproblems refer to the same n+1 index of the DP array so only 1 subproblem is solved which results in the incorrect answer.
So my question is:
How can I convert this recurrence to a top-down DP program? Is there a general approach that I can follow for cases like this?
Upvotes: 0
Views: 506
Reputation: 1
You can do it the way you are trying but , I will suggest you an easy way to the problem Its o(n) and doesn't even require to store the array thus o(1) space.
Let us keep 2 variables min and max. which stores the minimum and the maximum product so far , we are keeping min marker due to -ve numbers as two negative numbers can product to large number.
rest is easy,
initialise min=1 and max=1 and ans=0(as qs says atleast one number needs to be there you can change this initialisation accordingly) i.e the first element.
start reading the input one element at a time say 'a' loop over length of the array
{
if(a>0)
max= a * max;
min=(1 < min * a) ? 1 : min * a ;
else if (a<0)
max=(1 > min * a) ? 1 : min * a ; min=max * a;
else
max=1; min=1;
ans=(ans > max) ? ans : max; // this is outside else
}
at the end of loop max will be the answer, happy coding :)
Upvotes: 0
Reputation: 3580
Your dp
state depends on both the current index n
and the current result p
. So you need to memoize the result in a 2D
array instead of using a 1D
array for just index.
private int f(int[] a, int p, int n, int[] dp) {
if(dp[n][p]!=0)
return dp[n][p];
if(n==a.length)
dp[n][p] = p;
else
dp[n][p] = max(p, f_m(a, p*a[n], n+1, dp), f_m(a, a[n], n+1, dp));
return dp[n][p];
}
Upvotes: 1