数组中连续元素的最大乘积

时间:2013-09-17 01:10:25

标签: algorithm

我在现场采访中被问到这个算法问题。由于我没有被要求签署NDA,我在这里发布答案。

给定一个不包含0的 REAL 数字数组,找到产生最大乘积的连续元素。算法应该以线性时间运行

我考虑过以下方法: 使用两个数组。第一个是使用DP构思记录当前最大绝对值产品,第二个数组记录到目前为止遇到的负元素数量。最终结果应该是最大的最大绝对值,负数的数量应该是偶数。

我认为我的方法会起作用,但在编码过程中被打断说它不起作用。 请告诉我上述方法中缺少的内容。

8 个答案:

答案 0 :(得分:40)

算法确实是O(n)。迭代数组时,使用变量存储到目前为止找到的最大值,一个变量用于存储以[i]结尾的子数组的最大值,另一个变量用于存储以[i]结尾处理的最小值负值。

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;
}

答案 1 :(得分:2)

您可以实现Kadane算法(http://en.wikipedia.org/wiki/Maximum_subarray_problem)的变体,该算法使用恒定的额外内存和问题大小的线性运行(没有额外的数组,...)

如果只给出严格的正数:

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

我还在处理带有负数的部分

或者更昂贵(及时)的方法如下,但这将使用负数:

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

哪个在常量内存和O(n²)时间内运行

答案 2 :(得分:0)

使用python表示法:

  • 在O(n)
  • 中计算min( prod( v[ 0: ] ), prod( v[ 1: ] ), ..., prod( v[ -1 ] ) )max( prod( v[ 0: ] ), prod( v[ 1: ] ), ..., prod( v[ -1 ] ) )
  • 根据maxpro(v) = max( maxpro(v[:-1]) * max( prod( v[ 0: ] ), prod( v[ 1: ] ), ..., prod( v[ -1 ] ) )的事实递归计算最大乘积。这也是O(n)

以下是代码:

#
n = 5
vmax = 10

#
v = nr.randint( 1, vmax, n )
v *= nr.randint( 0, 2, n ) * 2 - 1
#
print v

#
prod_res = np.zeros( ( 2, n ), int )
prod_res[ 0, 0 ] = prod_res[ 1, 0 ] = v[ 0 ]
for i in xrange( 1, n ) :
    prod_res[ 0, i ] = min( v[ i ], prod_res[ 1, i-1 ] * v[ i ], prod_res[ 0, i-1 ] * v[ i ] )
    prod_res[ 1, i ] = max( v[ i ], prod_res[ 1, i-1 ] * v[ i ], prod_res[ 0, i-1 ] * v[ i ] )
#
print prod_res

#
def maxpro_naive( v ) :
    return v[ 0 ] if ( len( v ) == 1 ) else max( maxpro_naive( v[ :-1 ] ), prod_res[ 1, len(v) -1 ] )
#
print maxpro_naive( v )

答案 3 :(得分:0)

暂时忽略负数......

A[i..j]表示A[i]*A[i+1]*...*A[j]

问题是找到max(A[i..j])

请注意A[i..j] = A[0..j] / A[0..i-1]

因此,如果我们为所有x计算A[0..x]

然后我们可以确定max(A[i..j]) = max(A[0..x]) / min(A[0..y])

答案 4 :(得分:0)

如果阵列中没有1,则处理该事物,并且在这种情况下产品不应为1。 这是我的代码:

#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;
}

答案 5 :(得分:0)

在O(n)结果中。通过将每个元素从左向右相乘并将它们保存在列表中,找到产生最大乘积的连续元素。如果新产品大于最后一个乘以下一个元素并更新列表。如果没有开始新的列表并重复。 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))

返回:

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

答案 6 :(得分:0)

我写下面的代码,用于查找输入数组中相邻整数值的最大乘积,假设产品也在int范围内 它只会循环n / 2次

int adjacentElementsProduct(int[] inputArray) {

    int maxProdct=inputArray[0]*inputArray[1];
//as we have already taken product of first two , start from 3rd and iterate till second last because we are checking the product of i+1 for every i
    for (int i=2; i<inputArray.length-1; i=i+2){
        if(inputArray[i-1]*inputArray[i] >inputArray[i]*inputArray[i+1]){
            if(inputArray[i-1]*inputArray[i]>maxProdct)
                maxProdct =inputArray[i-1]*inputArray[i];
        }
        else if(inputArray[i+1]*inputArray[i] > maxProdct)
            maxProdct=inputArray[i+1]*inputArray[i];



    }
//if its an even array the last element would have been covered while calculating product with second last, otherwise we would check the product for last and second last element and compare with maxProduct
    if(inputArray.length%2 !=0){
        if(maxProdct<inputArray[inputArray.length-1]*inputArray[inputArray.length-2]){
            maxProdct=inputArray[inputArray.length-1]*inputArray[inputArray.length-2];
        }
    }
    return maxProdct;

}

答案 7 :(得分:0)

如果我们想在 O(n)中求解,并允许对数组和 o(n)进行两次遍历,那么下面的代码将适用于所有Java中的 + ve -ve 值。

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);
    }
}