I was asked this algorithm question during my onsite interview. Since I was not asked to sign NDA, I post it here for an answer.
Given an array of REAL
In O(n) result. Find the consecutive elements that yield max product, by multiplying each element from left to right and saving them in a list. If the new product is bigger than the last multiply the next element and update the list. If not start a new list and repeat. Algorithm in Python 3.3 :
import numpy as np
x = [-500,-400,200,0.1,-100,20,-10,2]
prod_seq_lists = [[x[0], x[1]]] # Start assuming the first 2 elements have max product and save them in a list
product_result = [] # Contains the product of each list
for e in x[2:]: # Start for loop from 3rd element
if x[0] == 0 or x[1] == 0 or e == 0: # Raise error if there's a 0
raise IndexError('Found 0')
temp_b = np.prod(prod_seq_lists[-1]) # Calculate the product of the last list in max_prod_seq
temp_a = temp_b * e # Multiply the new_element
if temp_a >= temp_b: # If last_list*new_element >= last_list
prod_seq_lists[-1].append(e) # Append the new_element in your last_list
if e == x[-1]:
product_result.append(temp_a) # Save the product of the last list
else:
product_result.append(temp_b) # Save the product of each list
prod_seq_lists.append([e]) # Else, append append the new element in a new_list
print("Your array: ", prod_seq_lists)
print("The list with max product of consecutive elements: ", prod_seq_lists[np.argmax(product_result)]) # Get index of the maximum product and print that list
print("The max product of consecutive elements: ", max(product_result))
Returns :
Your array: [[-50, -40, 20], [0.1], [-100], [20], [-10], [90, 1000]]
The list with max product of consecutive elements: [90, 1000]
The max product of consecutive elements: 90000
Ignoring negative numbers for the moment...
Let A[i..j]
mean A[i]*A[i+1]*...*A[j]
The problem is to find max(A[i..j])
Notice that A[i..j] = A[0..j] / A[0..i-1]
So if we calculate A[0..x]
for all x.
We can then determine max(A[i..j]) = max(A[0..x]) / min(A[0..y])
You can implement a variant of the Kadane algorithm (http://en.wikipedia.org/wiki/Maximum_subarray_problem) who runs with constant extra memory and linear in the size of the problem (no extra array,...)
If only strict positive numbers are given:
def max_subarray_mul(A):
max_ending_here = max_so_far = 1
for x in A:
if x > 0
max_ending_here = max(1,max_ending_here*x)
max_so_far = max(max_so_far, max_ending_here)
return max_so_far
I'm still working on the part with negative numbers
Or a more expensive (in time) method is the following, but this will work with negative numbers:
def max_subarray_mul(A):
max_so_far = 1
n = length(A)
for i in 1...n:
x = A[i]
tmp = x
max_so_far = max(max_so_far,tmp)
for j in i+1...n:
tmp = tmp*A[j]
max_so_far = max(max_so_far,tmp)
return max_so_far
Which runs in constant memory and O(n²)
time
Taking care of the thing if there are no 1's in the array and the product coming should not be 1 in that case. Here is my code:
#include<bits/stdc++.h>
using namespace std;
int max(int x, int y)
{ return (y > x)? y : x; }
int min(int x, int y)
{ return (y < x)? y : x; }
bool search(int a[],int k,int n)
{
for(int i=0;i<n;i++)
{
if(a[i]==k)
return true;
}
return false;
}
int maxSubArrayProduct(int a[], int size)
{
int maxpos = 1, minneg=1, i;
int pro_max = 1;
for (i = 0; i < size; i++)
{
if(a[i]<0)
{
int temp=maxpos;
maxpos=max(maxpos,minneg*a[i]);
minneg=min(minneg,temp*a[i]);
}
if(a[i]==0)
{maxpos=1;minneg=1;}
if(a[i]>0)
{
maxpos=maxpos*a[i];
minneg=min(minneg,minneg*a[i]);
}
if(pro_max<maxpos)
pro_max=maxpos;
}
return pro_max;
}
/* Driver program to test maxSubArrayProduct */
int main()
{
int a[] = {-1,0,1};
int n = sizeof(a)/sizeof(a[0]);
int start=0,end=0;
int max_pro = maxSubArrayProduct(a, n);
if(max_pro==1)
if(search(a,1,n))max_pro=1;
else max_pro=0;
printf("Maximum contiguous product is %d\n", max_pro);
return 0;
}
The algorithm is indeed O(n). When iterating the array, use a variable to store the max value found so far, a variable to store the max value of subarray that ends at a[i], and another variable to store minimum value that ends at a[i] to treat negative values.
float find_maximum(float arr[], int n) {
if (n <= 0) return NAN;
float max_at = arr[0]; // Maximum value that ends at arr[i]
float min_at = arr[0]; // Minimum value that ends at arr[i]
float max_value = max_at;
for (int i = 1; i < n; i++) {
float prev_max_at = max_at, prev_min_at = min_at;
max_at = max(arr[i], arr[i] * prev_min_at, arr[i] * prev_max_at);
min_at = min(arr[i], arr[i] * prev_min_at, arr[i] * prev_max_at);
max_value = max(max_value, max_at);
}
return max_value;
}
If we want to solve in O(n) and allowed to take two traversals of array and o(n) extra space, my below code would work for all +ve and -ve values in Java.
import java.util.ArrayList;
import java.util.List;
public class largestProductOfTwoNumbers {
public static void main(String[] args) {
int result = 0;
int a[] = { -22, -5, 12, 6, 3, 4, 9, -11, 4, 5, 6, 8, 7, 7 };
int max = 0;
int curr = 0;
List<Integer> list = new ArrayList();
for (int i = 0; i < a.length - 1; i++) {
curr = a[i] * a[i + 1];
list.add(curr);
}
for (int i = 0; i < list.size(); i++) {
if (list.get(i) > max) {
max = list.get(i);
}
}
System.out.println(max);
}
}