Python实现C(m,n)/ A(m,n)排列组合数计算

排列组合

百度百科:传送门

组合C(m,n)

组合,是指从m个字符中选取n个字符,获得所有的组合的数量统计。

一般代数运算是:C(m, n) = m!/n!(m-n)! m为下标,n为上标
0= 1
速算方式是 C(m, n) = (m * (m-1) * ··· * (1+ m-n)) / n!
例:C(5,3) = (5* 4* 3) / 3= 10
首先是计算阶乘
def nn(n, j=0):
    '''
    j == 0 时,计算阶乘
    j != 0 时,计算 n * (n-1) * ··· * (1+j)
    '''
    a = 1
    for i in range(1+j, n+1):
        a = a * i
    return a
计算组合
def c(m, n):
    '''
    计算组合数Cmn,m为下标,n为上标
    '''
    a = nn(m, m-n)
    b = nn(n)
    # 因为n函数里的返回值 基数a = 1,且range计算值>=1
    # 所以无需考虑b==0
    return int(a / b)
结果
>>> print(c(5, 3))
10
>>> print(c(10, 1))
10
>>> print(c(10, 9))
10
>>>

排列A(m,n)

一般代数运算是:A(m, n) = m!/(m-n)! m为下标,n为上标
0= 1
例:A(5,3) = 5! / (5-3)! = 60
def a1(m,n):
    '''
    A(m,n) = m!/(m-n)!
    '''
    return int(nn(m) / nn(m-n))

完整代码

import time
import random

def debug_get_func_runtime(func):
    def inner(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print("function %s use time %s" % (func.__name__, (end - start)))
        return res, (end - start)

    return inner


dic = []
for j in range(10000):
    dic.append([random.randint(100, 200), random.randint(1,100)])


def nn(n, j=0):
    '''
    j == 0 时,计算阶乘
    j != 0 时,计算 n * (n-1) * ··· * (1+j)
    '''
    a = 1
    for i in range(1+j,n+1):
        a = a * i
    return a

def c1(m, n):
    '''
    计算组合数
    Cmn = 
    '''
    return nn(m) / (nn(n) * nn(m-n))

def c2(m, n):
    '''
    计算组合数Cmn
    '''
    a = nn(m, m-n)
    b = nn(n)
    return int(a / b)

def a1(m,n):
    '''
    A(m,n) = m!/(m-n)!
    '''
    return int(nn(m) / nn(m-n))

@debug_get_func_runtime
def test1():
    for k in dic:
        c1(k[0], k[1])

@debug_get_func_runtime
def test2():
    for k in dic:
        c2(k[0], k[1])

@debug_get_func_runtime
def test3():
    for k in dic:
        a1(k[0], k[1])

test1()
test2()
test3()


结果
function test1 use time 0.3269994258880615
function test2 use time 0.12499642372131348
function test3 use time 0.2750399112701416

那么问题来了,组合的速算方式 比 一般方法效率提升3倍。原因是少一次阶乘么?
2021/12/17 TBD

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AgtNN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值