Ruby - 检查数组中两个数字之和是否等于一个值的有效方法

时间:2016-09-01 13:38:59

标签: arrays ruby performance loops

这是我的问题:我有一个我需要迭代的28,123个数字的列表和一个6965个其他数字的数组,检查两个数字的总和(可以是相同的数字)是否具有相同的值28,123个数字。我想将它们放在一个新数组中,或将它们标记为true / false。到目前为止,我提出的任何解决方案效率极低。

如果我有以下内容,那么我想要的是一个愚蠢的版本:array = [1, 2, 5]而数字1 to 5将返回result = [2, 3, 4]或数组result = [false, true, true, true, false] < / p>

我读到了这个SE问题:Check if the sum of two different numbers in an array equal a variable number?但是在我的情况下我需要更高效的东西,或者可能采用不同的方法解决问题。它似乎也无法用于将两个相同的数字加在一起。

非常感谢任何帮助!

non_abundant(n)是一个返回前n个非丰富数字的函数。它几乎瞬间执行。

我的代码:

def contains_pair?(array, n)
  !!array.combination(2).detect { |a, b| a + b == n }
end

result = []
array = non_abundant(6965)

(1..28123).each do |n|
  if array.index(n) == nil
    index = array.length - 1
  else
    index = array.index(n)
  end
  puts n
  if contains_pair?( array.take(index), n)
    result << n
  end
end

2 个答案:

答案 0 :(得分:1)

numbers = [1, 2, 5]
results = (1..10).to_a

numbers_set = numbers.each_with_object({}){ |i, h| h[i] = true }

results.select do |item|
  numbers.detect do |num|
    numbers_set[item - num]
  end
end
#=> [2, 3, 4, 6, 7, 10]

您可以通过对数字进行排序并检查num是否大于item/2来添加一些优化。

复杂性为O(n*m),其中nm是两个列表的长度。

另一个优化是,如果数字列表长度小于结果列表(n << m),则可以通过首先计算数字列表中的所有可能总和来实现O(n*n)复杂度。

答案 1 :(得分:0)

您的算法效率最低的部分是您重新计算许多可能的组合总和, 28123 次。您只需要一次

以下是对代码的一个非常简单的改进:

array = non_abundant(6965)
combination_sums = array.combination(2).map {|comb| comb.inject(:+)}.uniq

result = (1..28123).select do |n|
  combination_sums.include? n
end

你的算法的其余部分似乎是试图弥补重新计算总和的原始性能错误 - 这是不再需要的。

您可能会进行进一步的优化,例如使用二进制搜索。但我猜这种改进已足以满足您的需求。