python 之递归实现排列

    前面写过一个 全排列 的递归,文章地址:https://blog.csdn.net/yzmumu/article/details/80786605  排列实现的方式与前面写过的全排列实现方式完全不同,无法进行改写,自能重新写

    本篇文章是关于 排列 P(n, k) 的递归实现,不同于全排列,是从 n 个元素中选取 k 个元素组成一个排列,求出所有可能的排列。

    由此可见:全排列是排列的一个特殊情况,实现排列就能实现全排列。

    排列的计算公式:  P(n, k) = n! / (n-k)!  并有 0!= 1

    排列实现的方式与前面写过的全排列实现方式完全不同,无法进行改写,自能重新写

    思路如下:

    元素的母本还是用:letters = 'abcdefghijklmnopqrstuvwxyz'

    P(n, k) 的递归基础是 list(letters[:n])

    递归链条是:遍历底层返回的列表,对元素进行再次遍历判读,将已经在元素中的字符去除,不再的字符逐个加在元素上,最后返回处理的结果

代码如下:

def permutation_nk_recursion(n, k, letters, m = '', k_letter = ''):
    '''
    递推实现不同排列的输出
    参数:
        n --> 参与排列的元素的总数量 n <= len(letters)
        k --> 选取参与排列的元素的个数, k <= n
        letters --> 参与排列的元素选取的母本
        m --> 在函数调用中保存并固定初始的最初 n-k 作为递归结束的判断标记
        k_letter --> 保存参与排列的元素的列表
        ps: m, k_letter 在递归中能保证不变的原因:在最外层的函数调用过程获得值更新后,被保护起来,
                                                  在随后的递归过程中,都是在外层函数之内,所以也在 m 和 k_letter 的作用域内
    '''
    # 根据实际输入的 n, k, letters 值初始化 m, k_letter
    if m == '':
        m = n - k
        k_letter = list(letters[:n])
    # 递归基础
    if n == m+1: return k_letter
    # 初始化 num_of_perm,用于保存结果
    num_of_perm = []
    # 遍历上一级返回的结果列表中的元素,并与 perm 进行关联
    for perm in permutation_nk_recursion(n-1, k, letters, m, k_letter):
        # 'temp_letter 的逻辑:通过 for 循环遍历 k_letter, 如果遍历的元素不再perm中,则添加到 temp_letter 中'
        temp_letter = [i for i in k_letter if i not in perm]
        # 循环将 temp_letter 中的元素添加到 perm 的后面
        num_of_perm += [perm + i for i in temp_letter]
    # 返回结果
    return num_of_perm

测试结果:

letters = 'abcdefghijklmnopqrstuvwxyz'
p_nk_r = permutation_nk_recursion(5, 3, letters)
p_nk_r.sort()
for i in range(len(p_nk_r)):
    print(p_nk_r[i], end = ' ' if (i+1)%12 != 0 else '\n')

########################################

abc abd abe acb acd ace adb adc ade aeb aec aed
bac bad bae bca bcd bce bda bdc bde bea bec bed
cab cad cae cba cbd cbe cda cdb cde cea ceb ced
dab dac dae dba dbc dbe dca dcb dce dea deb dec
eab eac ead eba ebc ebd eca ecb ecd eda edb edc




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值