Efficiency of searching a large list of numbers for certain digits

时间:2016-08-31 12:17:38

标签: ruby performance scalability

I have the following code where eratosthenes(N) returns an array of primes from 1 to N. What I want to do is remove any numbers from this list that contain the digits 0, 2, 4, 5, 6, 8. My code seems quite inefficient and wrong as it takes about 20 seconds (eratosthenes(N) is instantaneous) to get to just 100,000 and doesn't remove all the numbers I want it to. Is there a better, scalable solution to this problem?

N = 1_000_000
primes = eratosthenes(N)

primes.each do |num|
  if ["0", "2", "4", "5", "6", "8"].any? { |digit| num.to_s.include?(digit) }
      primes.delete(num)
  end
end

2 个答案:

答案 0 :(得分:1)

The problem with your approach is that each delete rewrites the array, and it's called for every deleted item, so the complexity of the algorithm is O(n^2) instead of O(n).

You should do something like this:

primes.reject!{|num| ["0", "2", "4", "5", "6", "8"].any? { |digit| num.to_s.include?(digit) }}

Or simply:

primes.reject!{|num| num.to_s[/[024568]/]}

It's just a matter of style, but I'd put everything together in one line (note the lack of ! in reject here):

primes = eratosthenes(N).reject{|num| num.to_s[/[024568]/]}

答案 1 :(得分:0)

I should think that you're looking for something like:

primes.reject!{|num| num % 2 == 0}