在O(1)

时间:2016-06-12 17:34:51

标签: c math combinations permutation combinatorics

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

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

6 个答案:

答案 0 :(得分:3)

请检查以下C计划。它需要nr作为输入并计算 n C r 值:

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;
}

要计算它,循环仅适用于&#39; r&#39;时间。

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

我猜你一定是对这两个复杂性命令感到困惑。希望,它会帮助你。

答案 1 :(得分:1)

如果你试图在恒定时间内计算ggmap(dub_map, base_layer = ggplot(data=df, aes(x = Longitude, y = Latitude, label=Station.Area))) + geom_point(fill = "green", alpha =0.8, size = 5, shape = 21) + geom_text() ,为什么不使用斯特林的近似值?

n!

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

C

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

来源:

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

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

答案 2 :(得分:0)

如果您使用的计算平台计算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)

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

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

答案 3 :(得分:0)

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);
    }
}

答案 4 :(得分:0)

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

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

答案 5 :(得分:-4)

  

有没有办法在O(1)

中找到组合数(而不是实际组合)

是的,您可以使用公式2 n -1找到数字n的组合数量而不重复,不包括空集。