这是我的问题:我有一个我需要迭代的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
答案 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)
,其中n
和m
是两个列表的长度。
另一个优化是,如果数字列表长度小于结果列表(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
你的算法的其余部分似乎是试图弥补重新计算总和的原始性能错误 - 这是不再需要的。
您可能会进行进一步的优化,例如使用二进制搜索。但我猜这种改进已足以满足您的需求。