Ruby内置的#permutation和#repeated_permutation方法的时间复杂度是多少?

时间:2016-09-14 15:07:50

标签: ruby-on-rails ruby algorithm time-complexity permutation

我一直在想Ruby的一些内置方法的时间复杂性,特别是这两个方法。我认为我自己想出的最好的排列方法是Θ(n·n!),Ruby的内置表现更好吗?如果是这样,请帮助我了解他们的算法。

2 个答案:

答案 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=20n!2432902008176640000n*n!

重复置换

48658040163532800000生成[1,2,...n].repeated_permutation(k)个k元素的数组。

复杂性应为n**kO(n**k)

对于O(k*n**k),它变为k=nO(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!)