如何计算具有N个元素的数组的M个元素的最大乘积

时间:2014-02-28 19:55:07

标签: algorithm

问题是 给定一个整数数组和一个长度L,找到一个长度为L的子数组,使得所有整数的乘积最大。    例:    输入:{4,1,-7,-8,9},3    输出:{ - 7,-8,9}

我编写了一个非常粗略且逻辑上有缺陷的代码,它没有提供任何合理的输出。也许有人可以指出我正确的方向

public class ProductProblem {
/*
 * Given an array of integers and a length L, find a sub-array of length L such that the products of all integers are the biggest.
   Example:
   Input: {4, 1, -7, -8, 9}, 3
   Output: {-7,-8,9}
 */
    int a[];
    int l;
    int maxProduct;

    public int findProduct(int[] input, int len,int product){
        int[] output=new int[len];
        for (int i=0;i<input.length;i++){
            if(len>=1){
                System.out.println(product);
                System.out.println("input[i]="+input[i]);
                product= product*input[i];
                findProduct(input,len-1,product);
                System.out.println("len="+len);
            }
            else {
                return product;
            }
        }
        if (product>maxProduct){
            maxProduct=product;
        }
        return product;
    }


    public static void main(String[] args){
        ProductProblem pp=new ProductProblem();
        int[] a={1,3,-6,3,5};
        pp.a=a;
        int max=pp.findProduct(a,3,1);
        System.out.println(max);
    }
}

4 个答案:

答案 0 :(得分:3)

假设子集不一定是连续的,下面的算法可以在O(n * Log(n))时间内解决它,其中n是数组长度。

关键观察是解决方案必须由前2 * k个负数和前L - 2 * k个正数组成,对于k的某个值。

  1. 将正数按降序排列为数组P
  2. 按负绝对值顺序
  3. 将负数排序为数组N.
  4. 特殊情况:如果P为空且L为奇数(表示否定结果),则从N的尾部返回L项。否则:
  5. 计算P和N的累积乘积,并分别存储在P'和N'中。即,P'[i] = P [1] * P [2] * ... * P [i]。设置P'[0] = N'[0] = 1。
  6. 将k从0循环到L / 2,并计算P'[L-2 * k] * N'[2 * k]。最大结果对应于最佳子集,然后可以从P和N再现。

答案 1 :(得分:1)

public int[] findProduct(int[] integers, int L) {
    int maxProduct = Integer.MIN_VALUE;
    int start = 0;
    for (int i = 0; i + L < integers.length; i++) {
        int tmp = 1;
        for (int j = i; j < i + L; j++) tmp *= array[j];
        if (tmp > maxProduct) {
            maxProduct = tmp;
            start = i;
        }
    }
    int[] retVal = new int[L];
    for (int i = start; i < start + L; i++) retVal[i - start] = integers[i];
    return retVal;
}

这里的原理是记录长度为L的每个连续子阵列(L指定为方法参数)的乘积,最大乘积存储在变量中。在函数结束时,将重新创建并返回最大产品子数组。

您可以按如下方式找到一组非连续的子阵列(然后以类似的方式查找最大乘积):

int[] subarrayL = new int[L];

public int[] findSubarrays(int[] integers, int L) {
    for (int i = 0; i < L; i++) {
        setSubarray(i, L);
    }
}

public void setSubarray(int[] integers, int i, int L) {
    for (int j = i; j < Math.min(integers.length, integers.length - L + i + 1); j++) {
        subarrayL[i] = integers[j];
        if (i + 1 < L) setSubarray(integers, i + 1, L);
    }
}

答案 2 :(得分:0)

如果子阵列应该是连续的,那么我们可以在O(N)时间内得到结果子阵列。代码如下:

public int[] findProduct(int[] input, int L) {

    if( L < input.length || L == 0 ) {
        //invalid case
        return 0;
    }

    int max_product = -2e9;
    int result_start = 0;
    int temp_result = 1;

    for(int i = 0; i < L - 1; i++) {
        temp_result *= input[i];
    }

    int left = 0;

    for (int right = L - 1; right < input.length; right++) {
        temp_result *= input[right];
        if (temp_result > max_product) {
            max_product = temp_result;
            result_start = left;
        }

        temp_result /= input[left]; // removing the leftmost item as that will not be included in next sub array.

        left ++;
    }

    int[] sub_array = new int[L];
    for (int i = 0; i < L; i++) sub_array[i] = integers[result_start + i];
    return sub_array;
}

答案 3 :(得分:0)

大多数语言允许您按数组值(或键值)排序,然后您可以将数组切片到前N个元素。

var array = sort(array)
var length = 10
var biggest = array_slice(array, 0, length);