Algorithm 如何计算数组中M个元素与N个元素的最大乘积

Algorithm 如何计算数组中M个元素与N个元素的最大乘积,algorithm,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 t

问题是 给定一个整数数组和一个长度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);
    }
}
公共类问题{
/*
*给定一个整数数组和一个长度L,找到一个长度L的子数组,这样所有整数的乘积都是最大的。
例子:
输入:{4,1,-7,-8,9},3
输出:{-7,-8,9}
*/
INTA[];
int l;
int-maxProduct;
公共int find产品(int[]输入,int len,int产品){
int[]输出=新的int[len];
对于(int i=0;i=1){
系统输出打印项次(产品);
System.out.println(“输入[i]=”+输入[i]);
产品=产品*输入[i];
findProduct(输入,len-1,产品);
System.out.println(“len=“+len”);
}
否则{
退货产品;
}
}
如果(产品>最大产品){
maxProduct=产品;
}
退货产品;
}
公共静态void main(字符串[]args){
ProductProblem pp=新产品问题();
int[]a={1,3,-6,3,5};
pp.a=a;
int max=pp.find产品(a,3,1);
系统输出打印项次(最大值);
}
}
public int[]find产品(int[]整数,int L){
int MAXDRODUCT=Integer.MIN_值;
int start=0;
对于(int i=0;i+LmaxProduct){
maxProduct=tmp;
开始=i;
}
}
int[]retVal=新的int[L];
对于(inti=start;i
这里的原理是记录长度为L(L指定为方法参数)的每个连续子数组的乘积,最大乘积存储在变量中。在函数结束时,将重新创建并返回最大乘积子数组

您可以按如下方式查找非连续子阵列集(然后以类似方式查找max product):

int[]子数组=新的int[L];
公共int[]findsubarray(int[]整数,int L){
对于(int i=0;i
如果子数组应该是连续的,那么我们可以在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;
}
public int[]find产品(int[]输入,int L){
如果(L最大产品){
最大产品=温度结果;
结果_开始=左;
}
temp_result/=input[left];//删除最左边的项,因为它不会包含在下一个子数组中。
左++;
}
int[]子数组=新的int[L];
对于(int i=0;i
大多数语言允许您按数组值(或键值)排序,然后您可以将数组切片到前N个元素

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

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

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

  • 将正数按降序排列到数组P中
  • 将负数按绝对值降序排列到数组N中
  • 特殊情况:如果P为空,L为奇数(表示负结果),则从N的尾部返回L项。否则:
  • 计算P和N的累积乘积,并分别存储在P'和N'中。也就是说,P'[i]=P[1]*P[2]*…*P[i]。设置P'[0]=N'[0]=1
  • 在k上从0循环到L/2,并计算P'[L-2*k]*N'[2*k]。最大结果对应于最佳子集,然后可以从P和N中复制该子集

  • 你说的子阵列是指一个连续的子阵列?噢,天哪,我没想到。我假设它不是连续的问题的根源是,对于像,
    1,2,-10,-200
    K=2
    ?除了/而不是实际代码之外,最好给出算法的高级描述/想法/伪代码。如果输入的所有元素都为零,则循环将超出范围。这个答案与您的答案类似,但它声称在O(n)时间内运行@维克多:问题略有不同。这里我们需要最好的集合,而在另一个问题中,我们需要最大积本身。我怀疑这里的问题有一个简单的线性解决方案,因为这会用一个比已知的更简单的线性时间解决方案来解决中值问题(或任何顺序统计)。链接的答案声称使用introselect来划分秩k处的绝对值。
    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;
    }
    
    var array = sort(array)
    var length = 10
    var biggest = array_slice(array, 0, length);