这是我对一个函数的解决方案,该函数应返回第一对两个素数,如果这些数字存在,则返回n,m之间的间隙为g,否则为零。
这是来自codewars.com的kata,它通过了初步测试。但是,当我提交它时,我收到一条错误消息,指出由于算法效率低下,需要花费太多时间(8000ms +)。
有人能指出我究竟是什么减慢了代码的速度,以及应该如何优化代码?
UITextfield
答案 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 }
会返回m
和n
之间所有素数的列表。这比使用m
和n
之间的所有数字构建数组具有更好的性能,如果它是素数,则检查此数组中的每个数字。值得注意的是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?
。
我不确定哪个版本会更快,并且运行一些基准测试可能是值得的。第一个版本需要更多内存,但计算量更少。性能可能取决于范围的大小。