python 之递归与非递归实现全排列

全排列:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。

当m=n时所有的排列情况叫全排列。公式:全排列数f(n)=n!(定义 n 为正整数)

# 给定的元素中,抽取一定数量的元素进行排列,求排列的总数
# 现以26个字母为例,从 a 开始,n 个字母的不同种排列数量为 n! 将这 n! 种不同排列进行输出  1 <= n <= 26

# eg: n == 3 时,输出为: bca cba cab acb bac abc

基本思路
    1. a    共 1 种情况(1!)
    2. ba --> ab  # 将 b 插入到已有元素 a 的前后位置    共 2 种情况(2!)

    3. cba cab --> bca bac acb abc  # 将 c 插入到已有元素 ba ab 的前面,中间,后面位置    共 6 种情况(3!)

非递归实现

因为需要用到阶乘,所以代码中定义了阶乘函数,并调用

def factorial_recursion(n):
    if n == 1: return 1
    return n * factorial_recursion(n-1)


def permutation_for_loop(n, letter):
    # 初始化一个列表,长度为排列的种数
    permutation_list = [0 for i in range(factorial_recursion(n))]
    # 创建临时列表,用于保存循环中元素的排列情况,初始化保存只有一个元素是的情况
    temporary_list = ['a']

    # 从 2 开始循环,因为只要一个元素的情况已保存
    for temp_x in range(2, n+1):
        # 计数,根据计数来更新列表 permutation_list 数据
        count = 0
        # for 循环遍历临时列表 temporary_list 获取每一个元素
        for temp_i in temporary_list:
            # for 循环遍历从列表 temporary_list 中取得的每一个元素的子元素
            for temp_j in temp_i:
                # 前缀插入,调用 str.replace() 方法返回一个新的字符串,并更新到 permutation_list 相应的位置,同时计数加 1
                permutation_list[count] = temp_i.replace(temp_j, letter[temp_x-1] + temp_j)
                count += 1
            # 完成后缀插入,计数加 1
            permutation_list[count] = temp_i + letter[temp_x-1]
            count += 1
        # 更新临时列表 permutation_list
        temporary_list = permutation_list[:factorial_recursion(temp_x)]

    # 返回结果
    return permutation_list

递归实现,用到了列表的双层推导

def permutation_recursion(n, letter):
    if n == 1: return [letter[n-1]]    # 基例
    return [i.replace(j, letter[n]+j) for i in permutation_recursion(n-1, letter) for j in i] \
           + [i+letter[n] for i in permutation_recursion(n-1, letter)]    # 递归链条,使用列表的双层推导实现列表

列表的双层推导

相当于把双层 for 循环中内层循环的表达式放到最前面,两个 for 循环按顺序写

sentence ='I am learning Python now!'
lst = [i for x in sentence for i in x]
for i in lst:
    print(i, end = '.')
# >>> I. .a.m. .l.e.a.r.n.i.n.g. .P.y.t.h.o.n. .n.o.w.!.

代码调用测试

letter = 'abcdefghijklmnopqrstuvwxyz'

pfl = permutation_for_loop(4, letter).sort()
for i in range(len(pfl)):
    print(pfl[i], end = ' ' if (i+1)%4 != 0 else '\n')

print('###########################################')

pr = permutation_recursion(4, letter).sort()
for i in range(len(pr)):
    print(pr[i], end = ' ' if (i+1)%4 != 0 else '\n')

# 运行结果如下:
abcd abdc acbd acdb
adbc adcb bacd badc
bcad bcda bdac bdca
cabd cadb cbad cbda
cdab cdba dabc dacb
dbac dbca dcab dcba
###########################################
abcd abdc acbd acdb
adbc adcb bacd badc
bcad bcda bdac bdca
cabd cadb cbad cbda
cdab cdba dabc dacb
dbac dbca dcab dcba

欢迎评论,给出改进意见!


猜你喜欢

转载自blog.csdn.net/yzmumu/article/details/80786605