问题的提示是:
编写一个采用数组数组的方法。如果数组中的一对数字总和为零,则返回这两个数字的位置。如果没有数字对总和为零,则返回
nil
。
我不确定如何解决这个问题以及最简单的方法。这会涉及.index方法吗?
def two_sum(nums)
end
two_sum([1,3,5,-3])
答案 0 :(得分:2)
与Ruby中的很多内容一样,有几种不同的方法可以做到这一点。解决这个问题的“经典”方法是使用两个嵌套循环:
def two_sum(nums)
for i1 in 0...nums.length
for i2 in i1...nums.length
# Inside this loop, nums[i1] represents one number in the array
# and nums[i2] represents a different number.
#
# If we find that the sum of these numbers is zero...
if nums[i1] + nums[i2] == 0
# Then we have our answer
return i1, i2
end
end
end
# At this point we've checked every possible combination and haven't
# found an answer, so a pair of numbers that sum to zero in that array
# must not exist. Return nil.
nil
end
另一种方法使用Ruby魔术以更具表现力的方式做同样的事情:
def two_sum(nums)
result_pair = nums.each_with_index.to_a.combination(2).find{|n1, n2| n1.first + n2.first == 0}
result_pair && result_pair.map(&:last)
end
这里的细分有点复杂。如果您想了解它,我建议您在Array
和Enumerable
上查看这些方法的文档。
答案 1 :(得分:0)
这是另一种方法:
def two_sum(nums)
seen = {}
nums.each_with_index do |n, i|
return seen[-1*n], i if seen.key?(-1*n)
seen[n] = i
end
nil
end
上述(你在一次通过中做得更快)所以O(n)。 与使用每个元素检查每个元素的天真方法相比,它确实使用了O(n)额外空间(但是那个元素是O(n ^ 2)
答案 2 :(得分:0)
这将返回总和为零的所有值对的偏移量。但是,返回值不是唯一的。例如,如果a = [1,1,1,-1,-1]
,汇总为零的对可能处于偏移[[0,3],[1,4]]
或[[1,3],[2,4]]
或其他值。
<强>代码强>
def match_zero_sums(arr)
h = arr.each_with_index.group_by(&:first)
h.keys.select { |k| k >= 0 }.each_with_object([]) do |k,a|
while (k==0 && h[k].size > 1) || (k>0 && h[k].any? && h[-k].any?)
a << [h[k].shift.last, h[-k].shift.last]
end if h.key?(-k)
end
end
示例强>
arr = [2,3,0,0,-2,-3,4,-3,0,3]
match_zero_sums(arr)
#=> [[0, 4], [1, 5], [9, 7], [2, 3]]
<强>解释强>
示例中的arr
:
enum0 = arr.each_with_index
#=> #<Enumerator: [2, 3, 0, 0, -2, -3, 4, -3, 0, 3]:each_with_index>
h = enum0.group_by(&:first)
#=> { 2=>[[2, 0]], 3=>[[3, 1], [3, 9]], 0=>[[0, 2], [0, 3], [0, 8]],
# -2=>[[-2, 4]], -3=>[[-3, 5], [-3, 7]], 4=>[[4, 6]]}
non_neg_keys = h.keys.select { |k| k >= 0 }
#=> [2, 3, 0, 4]
enum1 = non_neg_keys.each_with_object([])
#=> #<Enumerator: [2, 3, 0, 4]:each_with_object([])>
k,a = enum1.next
#=> [2, []]
k #=> 2
a #=> []
h.key?(-k)
#=> h.key?(-2) => true
所以执行while
循环:
k==0 && h[k].size > 1
#=> 2==0 && h[2].size > 1
#=> false && true => false
k>0 && h[k].any? && h[-k].any?
#=> 2>0 && h[2].any? && h[-2].any?
#=> true && true && true => true
false || true #=> true
所以计算:
a << [h[k].shift.last, h[-k].shift.last]
#=> a << [h[2].shift.last, h[-2].shift.last]
#=> a << [[2,0].last, [-2,4].last]
#=> a << [0,4]
所以现在:
a #=> [[0,4]]
和
h #=> { 2=>[], 3=>[[3, 1], [3, 9]], 0=>[[0, 2], [0, 3], [0, 8]],
# -2=>[], -3=>[[-3, 5], [-3, 7]], 4=>[[4, 6]]}
其余的计算方法类似。
答案 3 :(得分:0)
As always, there are usually many ways to solve a problem, especially with Ruby. If you had come from another language like Java or Python, there is a great chance you might not be already familiar with the each_with_index
or each.with_index
methods. Without over complicating the solution, just break the problem down into two separate while loops, and return the indexes of the pair that equates to zero if it exists. Ruby provides many methods to make life much easier, but without knowing the majority of them, you'll still be able to solve a plethora of problems with a solid foundation of the basics of programming.
def two_sum(nums)
i = 0
while i < nums.length
j = 0
while j < nums.length
if nums[i] + nums[j] == 0
return i, j
end
j += 1
end
i += 1
end
return nil
end`