【问题标题】:Ruby - Efficient method of checking if sum of two numbers in array equal a valueRuby - 检查数组中两个数字之和是否等于一个值的有效方法
【发布时间】:2017-01-09 10:21:24
【问题描述】:

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

因此,如果我有以下内容,我想要的简化版本是:array = [1, 2, 5] 和数字 1 to 5 将返回 result = [2, 3, 4] 或 result = [false, true, true, true, false] 的数组

我阅读了这个 SE 问题:Check if the sum of two different numbers in an array equal a variable number?,但在我看来,我需要一些更有效的方法,或者可能是解决问题的不同方法。它似乎也不适用于将两个相同的数字相加。

非常感谢任何帮助!

non_abundant(n) 是一个返回前 n 个 non_abundant 数字的函数。它几乎立即执行。

我的代码:

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

【问题讨论】:

  • 这似乎是一个 Set 的工作,因为您可以获得比使用数组更有效的查找。
  • 我对 ruby​​ 还很陌生,还没有使用过套装。我在寻找什么方法?
  • “两个数字”是指两个数字的总和,对吧?
  • 是的。错字。现已修复。
  • 标题写着“两个不同的数字”,这与“任意两个数字(可以是同一个数字)”相矛盾

标签: arrays ruby performance loops


【解决方案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 &lt;&lt; m),您可以通过首先计算数字列表中所有可能的总和来实现 O(n*n) 复杂度。

【讨论】:

    【解决方案2】:

    您的算法中最低效的部分是您重新计算许多可能的组合总和,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
    

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

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

    【讨论】:

    • 我会将uniq 更改为to_set(以及开头的require 'set')。这可以大大提高性能。
    猜你喜欢
    • 1970-01-01
    • 2015-05-25
    • 2015-03-22
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2021-03-08
    相关资源
    最近更新 更多