我正在查看python中的数学库内置的是否是“多集置换”。
我知道可以编程,但是目前我还不是python专家。所以我不能做复杂的方法。这里有人可以吗?
https://en.wikipedia.org/wiki/Permutation#Permutations_of_multisets
我遇到了编程方面的挑战(我不是学生,但我想提高自己),但是我的解决方案不够快(很多测试用例经常超时)。但是这个问题听起来很简单:如果您只能向右和向下移动,矩阵中从左上角到右下角有多少种出口方式。 我真的不想代替我解决任何问题。我只需要一些建议。我尝试了Pascal矩阵,该矩阵有效但很慢。我认为“多集置换”是我的解决方案,因为如果矩阵MxN(1≤M,N≤106)表示D M-1和R N,则存在两种类型的步骤D,R -1个步骤:n = N + M-2,m1 = M-1,m2 = N-1
答案 0 :(得分:1)
请注意,您的初始设置有误,因此在这里您实际上不需要多集排列。
问题听起来很简单:从左上方到左侧有多少种退出方式 如果只能上下左右移动,则在矩阵的右下角
NxM
矩阵的基本移动序列包含精确的N
下移和M
右移。有C(N+M, M)
(nCr
,combinations个数字,binomial coefficient)的方法来制作这种序列。
从第二个链接开始的Python计算nCr值的实现(我添加了整数除法)利用了非常理想的算法-它使选择适当的k
的步骤数量减至最少,并避免了由于同时进行乘法和除法而产生的中间值太大。请注意,对于您的情况,参数为n = N+M
和k = 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