C++ 二项式系数太慢

Quo*_*ane 3 c++ math recursion

我尝试通过帕斯卡三角形进行递归来计算二项式系数。它对于小数量来说效果很好,但是 20 up 要么非常慢,要么根本不起作用。

我尝试查找一些优化技术,例如“chaching”,但它们似乎并没有真正很好地集成在 C++ 中。

如果对您有帮助的话,这是代码。

int binom(const int n, const int k)
{
    double sum;

    if(n == 0 || k == 0){
            sum = 1;
    }
    else{
    sum = binom(n-1,k-1)+binom(n-1,k);
    }

    if((n== 1 && k== 0) || (n== 1 && k== 1))
       {
           sum = 1;
       }
    if(k > n)
    {
        sum = 0;
    }

    return sum;

}

int main()
{
int n;
int k;
int sum;

cout << "Enter a n: ";
cin >> n;
cout << "Enter a k: ";
cin >> k;

Summe = binom(n,k);

cout << endl << endl << "Number of possible combinations: " << sum << 
endl;

}
Run Code Online (Sandbox Code Playgroud)

我的猜测是该程序浪费了大量时间来计算它已经计算出的结果。它必须以某种方式记住过去的结果。

Bia*_*sta 5

我的猜测是该程序浪费了大量时间来计算它已经计算出的结果。

这绝对是真的。

关于这个主题,我建议您看看动态编程主题

有一类问题需要指数级的运行时复杂性,但可以使用动态编程技术来解决。这会将运行时复杂度降低到多项式复杂度(大多数时候,以增加空间复杂度为代价)。


动态规划的常见方法有:

  • 自上而下(利用记忆和递归)。
  • 自下而上(迭代)。

以下是我的自下而上的解决方案(快速且紧凑):

int BinomialCoefficient(const int n, const int k) {
  std::vector<int> aSolutions(k);
  aSolutions[0] = n - k + 1;

  for (int i = 1; i < k; ++i) {
    aSolutions[i] = aSolutions[i - 1] * (n - k + 1 + i) / (i + 1);
  }

  return aSolutions[k - 1];
}
Run Code Online (Sandbox Code Playgroud)

该算法具有运行时复杂度O(k)和空间复杂度O(k)。事实上,这是一个线性的。

此外,该解决方案比递归方法更简单、更快。它对CPU 缓存非常友好

另请注意,不依赖于n.

我利用简单的数学运算并获得以下公式实现了这一结果:

(n, k) = (n - 1, k - 1) * n / k
Run Code Online (Sandbox Code Playgroud)

关于二项式系数的一些数学参考


笔记

该算法实际上并不需要 的空间复杂度O(k)事实上,第 i步的解仅取决于(i-1)-th。因此,不需要存储所有中间解,只需存储上一步的中间解即可。这将使算法的O(1)空间复杂度增加。

但是,我更愿意将所有中间解决方案保留在解决方案代码中,以更好地展示动态编程方法背后的原理。

这是我的带有优化算法的存储库

  • 我相信这是一个比仅仅提出一个解决问题的程序更好的答案,因为它讲述了一些基本概念,可以在其他情况下帮助 OP。 (3认同)