我需要一种方法来接收不同长度和内容的字符串,返回排列的数量而不重复。我写了以下内容来试图解决这个问题
def permutations(n)
k = n.to_s.chars.uniq.length
e = n.to_s.length
m = (1..e).reduce(1, :*)
p = (1..k).reduce(1, :*)
l = m / p
case
when k == 1 then 1
when k < e then l
else m
end
end
以上是返回一些我已经困惑了几天的结果,我已经意识到,uniq
需要检查的重复值超过1组。
如果我通过bbbb789
,我会210
这是正确的。但是,如果我有一个包含两个重复项的集合,例如73839
,则预期结果为60 but I reach 5
我昨天意识到问题所在,但我无法找到重复数据的方法
我的第一个解决方法是使用
k = n.to_s.chars.uniq.length
m = n.to_s.chars.length
return 1 if k <= 1
n.to_s.chars.permutation(m)to_a.uniq.size
这也有效,但需要一个年龄来循环更长的集合的所有排列
答案 0 :(得分:2)
TL; DR:
def factorial(n)
(1..n).inject(1, :*)
end
str = '73839'
# https://stackoverflow.com/questions/5470725/how-to-group-by-count-in-array-without-using-loop
chars_count = str.split('').inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
# https://stackoverflow.com/questions/9560335/ruby-hash-to-array-of-values
chars_fact = chars_count.values.inject(1) {|result, element| result*factorial(element)}
p "There are #{factorial(str.length)/chars_fact} permutations without duplicates."
解释不是很好:
嗯,这主要是一个数学问题:
注意:当我写n!你应该阅读&#34; factorial n&#34;它代表整数1 * 2 * ... * n。您可以在此处找到ruby实现:https://stackoverflow.com/a/12415362/4480140
如果你有n和&m 39,那么找到没有重复的排列数的公式是n选择m + n,即(m + n)!/(n!* m !)。
然后,如果我们有'aazzerty&#39;我们是说我们有一个和一个人。所以我们有'aabbbbbb&#39;,我们有2种选择8种置换方式。其中一种可能的排列是&#39; bbabbbab&#39;然后我们对b进行了改变。我们知道这些b包含2个z和1个(e,r,t,y)。我们将置换所有不是z或a的东西。我们有2种选择6种方法。我们重复这个过程......
最后,排列数为(2选8)(2选6)(1选4) ... (1选2)。我们可以取消,实际上我们得到8!/(2!* 2!* 1!* 1!* 1!* 1!)。
基本上,我们必须计算每个角色的数量,取所有这些数字的阶乘,将它们相乘。这是分母,分子是字符串长度的阶乘。