Ruby - 添加到特定给定输入的数组中的对的总和

时间:2017-03-29 03:15:12

标签: arrays ruby

我正在处理红宝石问题并且我的解决方案有效。但是,它不适用于更大的测试用例,因为处理时间太长。

该方法需要两个输入,一个数字数组和一个数字。

目标是找到数组中的前两个数字,其总和是输入中提供的数字。

第一对意味着该对中的最高索引低于数组中添加到该数字的任何其他对的最高索引。

示例 - ([10,5,2,3,7,5],10)

答案应该是[3,7],而[5,5]也总和为10,最后5的索引是5,索引7是4,所以[3,7]首先出现。

def sum_pairs(ints, s)
  return nil if ints.empty? || ints.nil?

  x = ints.combination(2).select {|x, y| x + y == s}

  return nil if x.nil? || x.empty?

  ints.rindex(x[0][1]) > ints.rindex(x[-1][1]) ? x.last : x.first 

end

我的代码适用于除大型数组之外的所有测试用例。

我想知道是否有内置方法可以提供帮助,或者我是否需要以不同方式循环遍历数组。

2 个答案:

答案 0 :(得分:7)

使用Set时,此问题只需要一次传递:

require 'set'

def sum_pairs(ints, s)
  already_seen = Set.new
  ints.each do |int|
    return [s - int, int] if already_seen.include?(s - int)
    already_seen.add(int)
  end
  nil
end

sum_pairs([10, 5, 2, 3, 7, 5], 10)
# [3, 7]
sum_pairs([10, 5, 2, 3, 7, 5], 20)
# nil

它以正确的顺序输出结果,并且比其他解决方案快得多。

答案 1 :(得分:3)

另一种方法可能是确保您的组合始终采用正确的偏好顺序,然后使用#find代替#select。标准Ruby #combination(2)对元素0和所有后面的元素([10,5],[10,2],[10,3],[10,7],[10,5])然后对索引1所有后来的元素([5,2],[5,3],[5,7],[5,5])等等。

您可以编写一个新的modified_combination方法,将元素1与所有早期元素([5,10])配对,然后将元素2与所有早期元素([2,10],[2,5])配对元素3([3,10],[3,5],[3,2])等等。这将确保具有最小的较大索引号的对总是在列表中的第一个。

现在你可以做到:

x = ints.modified_combination.find { |x, y| x, y == s }.reverse

请记住,如果modified_combination返回枚举器而不是数组,这将最有效地工作(尽管在任何情况下它都会比原始方法更有效)。

如果您不想深入研究创建一个返回枚举器的方法,那么这是一个快速而肮脏的解决方案,可以实现同样的目标:

def sum_pairs(ints, s)
  (1...ints.size).each do |x|
    (0...x).each do |y|
      return [ints[y], ints[x]] if ints[x] + ints[y] == s
    end
  end
  nil
end