【问题标题】:Find number of combinations, nCr in O(1)在 O(1) 中查找组合数 nCr
【发布时间】:2016-10-13 03:06:00
【问题描述】:

有没有办法在 O(1) 中找到组合的数量(不是实际的组合)?我在这里读到了答案-time and space complexity of finding combination (nCr)。答案是需要 O(n!) 才能找到实际组合,但只需要 O(1) 才能找到此类组合的数量。我无法理解如何做到这一点。请解释我如何在 O(1) 中做到这一点。这里,O(1) 是时间复杂度。

[编辑]:我遇到的主要问题是如何实现 n!在 O(1) 中。

【问题讨论】:

  • 动态生成查找表。
  • 从头开始你无法计算 n!在 O(1) 中。可能是关于在存储阶乘值后查找 ncr 的帖子
  • 你可以用Stirling's approximation找到一个近似阶乘。
  • 你有任何理由相信这是可能的吗?
  • @templatetypedef 不,我没有任何强烈的理由相信这一点。只是两个人在我提到的链接上说了同样的话,所以无论如何这是问它是否可能的地方。

标签: c math combinations permutation combinatorics


【解决方案1】:

请查看以下C 程序。它以nr 作为输入并计算nCr 值:

int main(){
    int n, r;
    scanf("%d", &n);
    scanf("%d", &r);

    /*
    *  nCr = n! / !(n-r) / !(r)
    *      = n * n-1 * n-2 * .... * 1 / (n-r * n-r-1 * .. * 1) / 
    *           (r * r-1 * ... * 1)
    *      = n * n-1 * n-2 * n-r+1 / (r * r-1 * ... * 1)
    *      
    */

    int result = 1;
    int i;

    for (i=0; i<r; i++){
        result *= (n-i);    // n * n-1 * n-2 * .... * n-(r-1)
        result /= (i+1);    // r * r-1 * ... * 1
    }

    /*  The loop is going to run only r times for any n
     *  Time to calculate nCr : O(r)
     *  Space complexity: O(1)
    */

    printf("Result of C(%d, %d) = %d", n, r, result);

    return 0;
}

为了计算它,循环只运行 'r' 次。

因此,计算 nCr 值的时间复杂度为 O(r) 但是空间复杂度是O(1)

我想您一定对这两个复杂性顺序感到困惑。希望对你有帮助。

【讨论】:

  • 也许你是对的,在我提到的链接上回答的人在时间和空间上感到困惑,所以他专门把它写成时间复杂度,也让我感到困惑。
【解决方案2】:

如果您想在恒定时间内计算n!,为什么不使用斯特林近似?

n! \approx sqrt(2 * pi * n) * (n / e)^n

C:

pow( n, n ) * exp( -n ) * sqrt( 2.0 * PI * n );

我认为这将使您获得最接近恒定时间,每个操作的实际运行时间取决于架构。

来源:

https://en.wikipedia.org/wiki/Stirling%27s_approximation

https://github.com/ankurp/C-Algorithms/blob/master/factorial/fact.c

【讨论】:

    【解决方案3】:

    如果您使用的计算平台计算 n!,nCr 的运行时复杂度只能在 O(1) 内!在 O(1) 中。在标准计算机上,情况并非如此。

    但我们可以使用 exp(n) 和 log(n) 通常是 an O(1) operation for IEEE doublesimplement an approximation of log(n!) - 基于斯特林近似 - 在 O(1) 中的事实:

    logf(n) = log(n!) = (n – 0.5) * log(n) – n + 0.5 * log(2 * PI) + 1/(12 * n)
    

    如果我们将它与 n ≤ 255 的 log(n!) 的查找表结合起来,我们仍将有至少 14 个有效数字,并且我们可以计算出很好的 nCr 近似值,如下所示:

    binomial(n, r) = exp(logf(n) - logf(n - r) - logf(r))
    

    【讨论】:

      【解决方案4】:

      Ajeet's answer 应该被接受,但我认为它可以改进为Min(O(r),O(n-r)),如果减少它仍然是O(r)

      import java.util.Scanner;
      
      public class Main {
      
          public static void main(String[] args) {
              Scanner sc = new Scanner(System. in );
              int n = sc.nextInt();
              int r = sc.nextInt();
              // choose smaller one
              if (n - r < r) { 
                  r = n - r;
                  System.out.printf("Change %d to %d\n", n - r, r);
              }
              /*
               * nCr  = n! / ((n-r)! * (r)! )
               *      = (n * n-1 * n-2 * .... * 1) / ( (n-r * n-r-1 * .. * 1) * (r * r-1 * ... * 1) )
               *      = (n * n-1 * n-2 * n-r+1) / (r * r-1 * ... * 1)
               */
      
              int result = 1;
      
              for (int i = 0; i < r; i++) {
                  result *= (n - i); // n * n-1 * n-2 * .... * n-(r-1)
                  result /= (i + 1); // r * r-1 * ... * 1
              }
      
              /*
               * The loop is going to run only r times or (n-r) times for any n Time to calculate nCr : Min ( O(r) , O(n-r) )
               * Space complexity: O(1)
               */
              System.out.printf("Result of C(%d, %d) = %d", n, r, result);
          }
      }
      

      【讨论】:

        【解决方案5】:

        在某些用例中,最好通过生成帕斯卡三角形来预先计算 O(n^2) 中的所有答案,以便查询是 O(1)。

        其他时候你只需要计算 n!一个一个,所以复杂度是 O(n)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-20
          相关资源
          最近更新 更多