Ruby:测试列表中的任何数字是否在范围列表中的最快方法?

时间:2013-04-30 19:54:13

标签: ruby algorithm

检查列表中至少有一个数字是否在其他列表的一个范围内的一种可能方法如下:

# Input example:
# numbers = [123, 345, 567]
# ranges =[(1..10), (60..80), (200..400)]
def is_in(numbers, ranges)
  numbers.each do |n|
    ranges.each do |r|
      return true if r.include?(n)
    end
  end
  false
end

每种情况的最快方法是什么:

  1. 只有数字列表很大
  2. 只有范围列表很大
  3. 两者都很大

3 个答案:

答案 0 :(得分:3)

如果您的数字数组很大且有序,您可以使用Ruby 2.0的新二进制搜索Array#bsearch方法将范围覆盖率检查从O(N)复杂度加速到O(logN)。

class Range
  def fast_cover_any?(ordered_arr)
    lo = first
    probe = ordered_arr.bsearch {|x| x >= lo}
    probe && exclude_end? ? probe < last : probe <= last
  end
end

ranges.any? { |r| r.fast_cover_any?(numbers) }

答案 1 :(得分:1)

ranges =[(1..10), (60..80), (200..400)]

numbers = [123, 700, 567]
numbers.any?{|x| ranges.any? {|y| y.include? x}} #=> false

numbers = [123, 400, 567]
numbers.any?{|x| ranges.any? {|y| y.include? x}} #=> true

使用ordered list

ranges =[(1..10), (60..80), (200..400)]

numbers = [123, 300, 567]
p numbers.sort.any?{|y| ranges.sort_by(&:first).bsearch{|x| x.include? y}} #=> true

numbers = [123, 700, 567]
p numbers.sort.any?{|y| ranges.sort_by(&:first).bsearch{|x| x.include? y}} #=> false

答案 2 :(得分:1)

简单的答案是将一个数据结构存储在有组织的结构中,并搜索其他列表的元素。

假设你有两个长度为m和n的列表x和y。

如果m&lt;&lt; n:排序x并在排序列表中找到y中的元素

如果m&gt;&gt; n:排序y并在排序列表中找到x中的元素

如果它们大小相同,请选择其中任何一个进行排序。

如何组织范围: 使用每个范围的开头对列表进行排序。如果两个范围重叠合并它们。最后,您将得到一个根据范围的起点排序的非重叠范围列表。