ruby - 可能效率低下的算法

时间:2016-10-03 05:08:55

标签: ruby algorithm

这是我对一个函数的解决方案,该函数应返回第一对两个素数,如果这些数字存在,则返回n,m之间的间隙为g,否则为零。

这是来自codewars.com的kata,它通过了初步测试。但是,当我提交它时,我收到一条错误消息,指出由于算法效率低下,需要花费太多时间(8000ms +)。

有人能指出我究竟是什么减慢了代码的速度,以及应该如何优化代码?

UITextfield

1 个答案:

答案 0 :(得分:2)

试试这个:

require 'prime'

def gap(g, m, n)
  primes = Prime.each(n).select { |p| p >= m }
  primes[0..-2].zip(primes[1..-1]).find { |a, b| b - a == g } 
end

gap(2, 1, 1000)
#=> [3, 5]

gap(6, 1, 1000)
#=> [23, 29]

Prime.each(n).select { |p| p >= m }会返回mn之间所有素数的列表。这比使用mn之间的所有数字构建数组具有更好的性能,如果它是素数,则检查此数组中的每个数字。值得注意的是Prime.each使用了eratosthenes'筛选算法作为默认值。

primes[0..-2].zip(primes[1..-1])构建每对的数组。这不是迭代primes数组中每对的最有效方法,但我认为它比处理索引更好。

这可能是另一种选择:

require 'prime'
require 'set'

def gap(g, m, n)
  primes = Set.new(Prime.each(n).select { |p| p>= m })
  primes.each { |prime| return [prime, prime + g] if primes.include?(prime + g) }
end

第二个版本没有构建包含所有对的新数组,而是只检查prime + g数组中是否包含primes的每个素数。我使用了Set,因为它改进了对include?的{​​{1}}次查询(而数组上的O(1)则为include?

我不确定哪个版本会更快,并且运行一些基准测试可能是值得的。第一个版本需要更多内存,但计算量更少。性能可能取决于范围的大小。