m元素的所有组合与n个元素的数组的乘法和

时间:2014-05-08 08:55:07

标签: algorithm

假设我有一个数组{1, 2, 5, 4}m = 3。 我需要找到:

1*2*5 + 1*2*4 + 1*5*4 + 2*5*4

即m元素的所有组合与n个元素的数组相乘的总和。

可能的解决方案之一是找到所有组合,然后解决它,但这将是O(nCm)解决方案。有没有更好的算法?

3 个答案:

答案 0 :(得分:5)

这个问题相当于计算给定根(Vieta's theorem)的多项式的Mth系数。 Delphi中的自适应算法(O(N)存储器和O(N ^ 2)时间):

 function CalcMultiComb(const A: array of Integer; const M: Integer): Integer;
  var
    i, k, N: Integer;
    Coeff: TArray<Integer>;
  begin
    N := Length(A);
    if (N = 0) or (M > N) then
      Exit;
    SetLength(Coeff, N + 1);

    Coeff[0] := -A[0];
    Coeff[1] := 1;
    for k := 2 to N do begin
      Coeff[k] := 1;
      for i := k - 2 downto 0 do
        Coeff[i + 1] := Coeff[i] - A[k-1] * Coeff[i + 1];
      Coeff[0] := -A[k-1] * Coeff[0];
    end;

    Result := Coeff[N - M];
    if Odd(N - M) then
      Result := - Result;
  end;

调用CalcMultiComb([1,2,3,4],M),M = 1..4给出结果10,35,50,24

答案 1 :(得分:4)

我脑子里有一个动态编程解决方案,只是想分享。时间复杂度为O(k * n ^ 2),n为总数。

我们的想法是,我们开始填写从0到k -1的每个位置。因此,如果我们假设位置ith,则此位置的填充数量为a,因此以a开头的所有组合的总和将是a的总和(i + 1)th倍从(a + 1)

开始的位置data的所有组合

注意:我已经更新了解决方案,因此可以使用任何数组public int cal(int n, int k , int[]data){ int [][] dp = new int[k][n + 1]; for(int i = 1; i <= n; i++){ dp[k - 1][i] = data[i - 1]; } for(int i = k - 2; i >= 0; i--){ for(int j = 1 ; j <= n; j++){ for(int m = j + 1 ; m <= n; m++){ dp[i][j] += data[j - 1]*dp[i + 1][m]; } } } int total = 0; for(int i = 1; i <= n; i++){ total += dp[0][i]; } return total; } ,我的语言是Java,所以您可以注意到数组的索引是基于0的,从0开始到n-1

{{1}}

答案 2 :(得分:2)

我想出了同样的问题。我也通过Vieta算法找到了解决方案。我调整算法而不是计算不需要的多项式系数。复杂度为O(N * M)。我查看了DFT和FFT,但如果M足够小,这种方法甚至比快速傅里叶变换算法更快。这是java btw。

public BigInteger sumOfCombMult(Integer[] roots, int M)
{
    if (roots.length < M)
    {
        throw new IllegalArgumentException("size of roots cannot be smaller than M");
    }

    BigInteger[] R = new BigInteger[roots.length];

    for (int i = 0; i < roots.length; i++)
    {
        R[i] = BigInteger.valueOf(roots[i]);
    }

    BigInteger[] coeffs = new BigInteger[roots.length + 1];

    coeffs[0] = BigInteger.valueOf(roots[0]);

    int lb = 0;

    for (int i = 1; i < roots.length; i++)
    {
        lb = Math.max(i - M, 0);

        coeffs[i] = R[i].add(coeffs[i - 1]);

        for (int j = i - 1; j > lb; j--)
        {
            coeffs[j] = R[i].multiply(coeffs[j]).add(coeffs[j - 1]);

        }

        if (lb == 0)
        {
            coeffs[0] = coeffs[0].multiply(R[i]);
        }
    }

    return coeffs[roots.length - M];
}