输出所有的排列组合

本文介绍了如何用Python编程实现从n个数中挑选m个数的排列和组合问题,通过递归和回溯法详细解释了排列和组合的区别,并提供了相应的代码示例。
摘要由CSDN通过智能技术生成

       排列和组合是数学里大家都很熟悉的概念,如果问从5个数中挑出3个数的排列有多少种,答案是P(5, 3) = 5 * 4 * 3,如果问从5个数中挑出3个数的组合有多少种,答案是C(5, 3) = P(5, 3)/3! = 5 * 4 * 3 / 1 * 2 * 3,但如果要求把这些排列组合的情形都列出来,那该如何呢?

       把这个问题进一步普遍化,列出从n个数中挑出m个数的所有排列/组合,该如何实现?

       先看排列的情形。

       从经验出发,挑m个数,自然采用m步,每一步挑选一个数,挑够了m个数,便输出一个排列。需要注意的是前面步骤挑出的数在后面不能再出现,也就是要记住前面步骤里已经挑选的数,还要注意的是当输出了一个排列,要计算下一个排列的时候,并不是又要从第一个数重新开始挑,而是采用回溯法,从最后一个数开始,为它挑一个新数,如果还可以挑出一个新的数,挑出那个数,前面的数保留不变,输出排列,如果不能再挑出一个新数,则回退到倒数第二个数,为倒数第二个数挑出一个新的数,然后挑最后一个数,输出排列,如果不能为倒数第二个数挑一个新数,则回退到倒数第三个数,以此类推,下面看代码实现。

def arrange(n, m):
    if 0 == m:
        yield []
        return
    mark = bytearray([0] * n)
    res = list([-1] * m)
    step = 0
    def choice(val):
        ret = -1
        for i in range(n):
            if 0 == mark[i] and i > val:
                mark[i] = 1 #lock the chosen value
                ret = i
                break
        if val != -1: 
            mark[val] = 0 #release the old value, it was locked previously
        return ret
    while step > -1:
        if step < m - 1:
            res[step] = choice(res[step])
            if -1 == res[step]:
                step -= 1
            else:
                step += 1
        else:
            res[step] = choice(res[step])
            if -1 == res[step]:
                step -= 1
            else:
                yield res
    
for i in arrange(5, 3):
    print(i)

       

        这是排列的情形,那么组合呢?组合和排列的不同之处在于,在排列里1, 2, 3和2,3,1是两个排列,而在组合里,它们是同一个组合,既然如此,我们可以用1,2,3代表这个组合,也就是我们可以把组合看成正序的排列。输出所有组合的算法和排列如出一辙,只是更简单了,每一步可以挑选的值是有规律可循的,不需要记住前面步骤挑出的值,下面看代码。

def combination(n, m):
    if 0 == m:
        yield []
        return
    res = list([0]*m)
    step = 0
    res[step] = 0
    while step > -1:
        if step < m -1:
            if res[step] <= n - m + step:
                res[step + 1] = res[step] + 1
                step += 1
            else:
                res[step - 1] += 1
                step -= 1
        else:
            if res[step] < n:
                yield res
                res[step] += 1
            else:
                res[step - 1] += 1
                step -= 1

for i in combination(5, 2):
    print(i)
  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

__空无一人__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值