我一直在想Ruby的一些内置方法的时间复杂性,特别是这两个方法。我认为我自己想出的最好的排列方法是Θ(n·n!),Ruby的内置表现更好吗?如果是这样,请帮助我了解他们的算法。
答案 0 :(得分:2)
Array#permutation
返回带有ALTER TABLE CARS ADD CONSTRAINT price_speed_chk CHECK(speed >= 1200 OR price<=90000 );
数组的枚举器,因此时间复杂度至少为n!
。
我写了这个方法:
O(n!)
它对def slow_method(n)
(1..n).to_a.permutation.each do |p|
p
end
end
没有任何作用,期望强制生成所有排列。构建所有排列的数组会占用太多内存。
此方法在10到13之间被调用10次,以秒为单位的平均时间为:
p
t10 = 0.618895
t11 = 6.7815425
t12 = 82.896605
t13 = 1073.015602
看起来像是一个合理的近似值:
O(n!)
t13/fact(13)*fact(12)/t12 #=> 0.995694114280165
t13/fact(13)*fact(11)/t11 #=> 1.0142685297667369
t13/fact(13)*fact(10)/t10 #=> 1.0103498450722133
没有:
O(n*n!)
生成似乎是t13/(fact(13)*13)*fact(12)*12/t12 #=> 0.9191022593355369
t13/(fact(13)*13)*fact(11)*11/t11 #=> 0.8582272174949312
t13/(fact(13)*13)*fact(10)*10/t10 #=> 0.777192188517087
,但对生成的数组执行任何操作都会使整体复杂性达到O(n!)
。
为什么不是代O(n*n!)
?这可能来自以下事实:当递归生成O(n*n!)
时,[1,2,3,4,5].permutation
和[1,2]
的剩余排列相同。
[2,1]
已经非常缓慢,O(n!)
永远不会比10大得多,所以n
并不会更糟。对于O(n*n!)
,n=20
为n!
,2432902008176640000
为n*n!
。
48658040163532800000
生成[1,2,...n].repeated_permutation(k)
个k元素的数组。
复杂性应为n**k
或O(n**k)
。
对于O(k*n**k)
,它变为k=n
或O(n**n)
,甚至比O(n**(n+1))
更差。
答案 1 :(得分:0)
有算法迭代生成列表的所有排列。
如何?该算法以字典顺序生成[1,2,3,4,...,n]
的所有排列。给定一个排列,算法在O(1)
时间内生成下一个词典排列。
这些是步骤
k
,使得a[k] < a[k + 1]
,如果不存在这样的索引,则排列是最后的排列l
的最大索引k
,以便a[k] < a[l]
a[k]
的值与a[l]
a[k + 1]
反转到最终元素a[n]
复杂性是什么?
每个步骤都是O(1)
,并且有O(n!)
个排列,因此总复杂度为O(n!)
。