counting combinations and permutations efficiently

后端 未结 13 1952
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-02 12:38

I have some code to count permutations and combinations, and I\'m trying to make it work better for large numbers.

I\'ve found a better algorithm for permutations th

相关标签:
13条回答
  • 2020-12-02 12:59

    If you don't need a pure-python solution, gmpy2 might help (gmpy2.comb is very fast).

    0 讨论(0)
  • 2020-12-02 13:00

    For N choose K you could use Pascals triangle. Basically you would need to keep array of size N around to compute all the N choose K values. Only additions would be required.

    0 讨论(0)
  • 2020-12-02 13:02

    More efficient solution for nCr - space wise and precision wise.

    The intermediary (res) is guaranteed to always be int and never larger than the result. Space complexity is O(1) (no lists, no zips, no stack), time complexity is O(r) - exactly r multiplications and r divisions.

    def ncr(n, r):
        r = min(r, n-r)
        if r == 0: return 1
        res = 1
        for k in range(1,r+1):
            res = res*(n-k+1)/k
        return res
    
    0 讨论(0)
  • 2020-12-02 13:07

    Two fairly simple suggestions:

    1. To avoid overflow, do everything in log space. Use the fact that log(a * b) = log(a) + log(b), and log(a / b) = log(a) - log(b). This makes it easy to work with very large factorials: log(n! / m!) = log(n!) - log(m!), etc.

    2. Use the gamma function instead of factorial. You can find one in scipy.stats.loggamma. It's a much more efficient way to calculate log-factorials than direct summation. loggamma(n) == log(factorial(n - 1)), and similarly, gamma(n) == factorial(n - 1).

    0 讨论(0)
  • 2020-12-02 13:11

    You could input two integers and import math library to find the factorial and then apply the nCr formula

    import math
    n,r=[int(_)for _ in raw_input().split()]
    f=math.factorial
    print f(n)/f(r)/f(n-r)
    
    0 讨论(0)
  • 2020-12-02 13:12

    For Python until 3.7:

    def prod(
            items,
            start=1):
        for item in items:
            start *= item
        return start
    
    
    def perm(n, k):
        if k > n or k < 0 or n < 0:
            raise ValueError(
                'Values must be non-negative and n >= k in perm(n, k)')
        else:
            return prod(range(n - k + 1, n + 1))
    
    
    def comb(n, k):
        if k > n or k < 0 or n < 0:
            raise ValueError(
                'Values must be non-negative and n >= k in comb(n, k)')
        elif k > n - k:
            # return perm(n, k) // math.factorial(n - k)
            return math.factorial(n) // math.factorial(k) // math.factorial(n - k)
        else:
            # return perm(n, n - k) // math.factorial(k)
            return math.factorial(n) // math.factorial(n - k) // math.factorial(k)
    

    For Python 3.8+:

    • math.perm()
    • math.comb()
    0 讨论(0)
提交回复
热议问题