m的n次方排列 python

问题描述:一个位置上有m种可能,一共n个位置,求所有可能的排列

解法1:分解法

灵感来源于线性代数中的矩阵乘法。

数字结果计算过程不就是n个m相乘吗,我们可以把这个过程拆分为2个为一组的多个二元运算。

假设n=3,m=2

那 2^3=2*2*2=(2*2)*2=4*2

转换成数组也是一样的

所以我们可以定义一种特殊的乘法:两个数组中的元素两两组合

假设:m=[1,2]

m*m*m=(m*m)*m

m*m=[1,2]*[1,2]=[[1, 1], [1, 2], [2, 1], [2, 2]]

(m*m)*m=[[1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 2, 2], [2, 1, 1], [2, 1, 2], [2, 2, 1], [2, 2, 2]]

我们只需要使用这种特殊的乘法,每次都乘上一个m,n-1次运算后便可得到结果。

解法2:深度优先搜索/回溯法(非递归)(迭代法)

相当于一颗多叉树,每个非叶节点有m个子节点,深搜的一条路径便是一种排列。

我们可以加上层数信息来区分这些节点。

算法描述如下:

1.初始化:将m个元素入栈,层数为0,创建一个临时数组:temp 长度为n

2.如果栈非空,弹出栈顶元素,修改temp[层数]=栈顶元素,如果层数等于n-1则将temp加入到结果中否则将m个元素入栈,层数为depth+1

3.重复执行步骤2,直到栈为空

解法1代码:

def multiply(a,b):
    r=[]
    for i in a:
        for j in b:
            if isinstance(i,list):
                temp=i[:]
                temp.append(j)
                r.append(temp)
            else:
                r.append([i,j])
    return r

if __name__ == "__main__":
    a=[1,2]
    m=len(a)
    n=3
    b=a
    while n>1:
        a=multiply(a,b)
        n-=1
    print(a)
    print(len(a))

解法2代码:

if __name__ == "__main__":
    a = [1, 2, 3]
    m = len(a)
    n = 3
    depth=0
    stack=[]
    for i in range(m):
        stack.append([depth,a[i]])
    r=[]
    temp=[-1]*n
    while stack:
        v=stack.pop()
        depth=v[0]
        temp[depth]=v[1]
        if depth==n-1:
            r.append(temp[:])
        else:
            for i in range(m):
                stack.append([depth+1, a[i]])
    print(r)
    print(len(r))

结果示例:

猜你喜欢

转载自blog.csdn.net/weixin_42378324/article/details/106445820
今日推荐