给出一个整数列表和一个总和值,返回前两个值(从左开始),它们加起来形成总和。
例如,给定:
sum_pairs([10, 5, 2, 3, 7, 5], 10)
[5, 5]
(在[1, 5]
的索引[10, 5, 2, 3, 7, 5]
处)总计10
,[3, 7]
(在索引[3, 4]
处)总计10
。其中,整个[3, 7]
对都比较早,因此是正确的答案。
这是我的代码:
def sum_pairs(ints, s)
result = []
i = 0
while i < ints.length - 1
j = i+1
while j < ints.length
result << [ints[i],ints[j]] if ints[i] + ints[j] == s
j += 1
end
i += 1
end
puts result.to_s
result.min
end
它可以工作,但是效率太低,需要12000毫秒才能运行。嵌套循环是效率低下的问题。我该如何改善算法?
答案 0 :(得分:6)
Set
个数字,从空开始nil
可能是最佳选择应该超快,因为只有一个循环。一旦找到第一个匹配对,它也会终止,因此通常在得到答案之前,您甚至不会遍历每个元素。
作为一种风格,以这种方式使用while
是非常不符合Ruby的。在实施上述操作时,建议您使用ints.each do |int| ... end
而不是while
。
编辑:正如Cary Swoveland所评论的那样,出于一种奇怪的原因,我认为您需要索引,而不是值。
答案 1 :(得分:4)
require 'set'
def sum_pairs(arr, target)
s = Set.new
arr.each do |v|
return [target-v, v] if s.include?(target-v)
s << v
end
nil
end
sum_pairs [10, 5, 2, 3, 7, 5], 10
#=> [3, 7]
sum_pairs [10, 5, 2, 3, 7, 5], 99
#=> nil
我使用了Set方法来加快include?
的查找速度(而且,次要的是,仅保存唯一的值)。
答案 2 :(得分:1)
请尝试以下操作,因为它更具可读性。
def sum_pairs(ints, s)
ints.each_with_index.map do |ele, i|
if ele < s
rem_arr = ints.from(i + 1)
rem = s - ele
[ele, rem] if rem_arr.include?(rem)
end
end.compact.last
end
答案 3 :(得分:0)
一支班轮(最快?)
ary = [10, 0, 8, 5, 2, 7, 3, 5, 5]
sum = 10
def sum_pairs(ary, sum)
ary.map.with_index { |e, i| [e, i] }.combination(2).to_a.keep_if { |a| a.first.first + a.last.first == sum }.map { |e| [e, e.max { |a, b| a.last <=> b.last }.last] }.min { |a, b| a.last <=> b.last }.first.map{ |e| e.first }
end
是的,它不是很可读,但是如果您从ary.map.with_index { |e, i| [e, i] }
开始逐步添加方法,就很容易理解它的工作原理。