如何计算Python中多集置换的有效方法

时间:2019-07-03 14:48:46

标签: python math permutation

我正在查看python中的数学库内置的是否是“多集置换”。

我知道可以编程,但是目前我还不是python专家。所以我不能做复杂的方法。这里有人可以吗?

https://en.wikipedia.org/wiki/Permutation#Permutations_of_multisets enter image description here

我遇到了编程方面的挑战(我不是学生,但我想提高自己),但是我的解决方案不够快(很多测试用例经常超时)。但是这个问题听起来很简单:如果您只能向右和向下移动,矩阵中从左上角到右下角有多少种出口方式。 我真的不想代替我解决任何问题。我只需要一些建议。我尝试了Pascal矩阵,该矩阵有效但很慢。我认为“多集置换”是我的解决方案,因为如果矩阵MxN(1≤M,N≤106)表示D M-1和R N,则存在两种类型的步骤D,R -1个步骤:n = N + M-2,m1 = M-1,m2 = N-1

2 个答案:

答案 0 :(得分:1)

请注意,您的初始设置有误,因此在这里您实际上不需要多集排列。

  

问题听起来很简单:从左上方到左侧有多少种退出方式   如果只能上下左右移动,则在矩阵的右下角

NxM矩阵的基本移动序列包含精确的N下移和M右移。有C(N+M, M)nCrcombinations个数字,binomial coefficient)的方法来制作这种序列。

从第二个链接开始的Python计算nCr值的实现(我添加了整数除法)利用了非常理想的算法-它使选择适当的k的步骤数量减至最少,并避免了由于同时进行乘法和除法而产生的中间值太大。请注意,对于您的情况,参数为n = N+Mk = M

def binomialCoefficient(n, k):
    if k < 0 or k > n:
        return 0
    if k == 0 or k == n:
        return 1
    k = min(k, n - k) # take advantage of symmetry
    c = 1
    for i in range(k):
        c = c * (n - i) // (i + 1)
    return c

对于生成方式本身(如果需要),请考虑itertools.combinations

答案 1 :(得分:0)

您可以使用itertools中的permutations()函数来获取所有排列和一个跳过重复的集合。

from itertools import permutations

multiset = "MISSISSIPPI"
perms = iter(p for s in [set()] for p in permutations(multiset) if p not in s and not s.add(p))

count = 0
for p in perms:
    count += 1
print(count) # 34650

如果只需要计数,可以实现公式(在数学和集合的帮助下):

from collections import Counter
from math import factorial

def multisetPermutations(A):
    result = factorial(len(A))
    for m in Counter(A).values():
        result = result // factorial(m)
    return result

print(multisetPermutations("MISSISSIPPI")) # 34650