检查数组中的2个数字在Ruby中是否和为0
我已经研究这个问题几个小时了,我不明白为什么我不能让它正常运行。这种方法的最终目的是让数组中的两个数字相加等于零。这是我的密码:检查数组中的2个数字在Ruby中是否和为0,ruby,arrays,Ruby,Arrays,我已经研究这个问题几个小时了,我不明白为什么我不能让它正常运行。这种方法的最终目的是让数组中的两个数字相加等于零。这是我的密码: def two_sums(nums) i = 0 j = -1 while i < nums.count num_1 = nums[i] while j < nums.count num_2 = nums[j] if num_1 + num_2 == 0
def two_sums(nums)
i = 0
j = -1
while i < nums.count
num_1 = nums[i]
while j < nums.count
num_2 = nums[j]
if num_1 + num_2 == 0
return "There are 2 numbers that sum to zero & they are #{num_1} and #{num_2}."
else
return "Nothing adds to zero."
end
end
i += 1
j -= 1
end
end
我遇到的问题是,除非数组中的第一个和最后一个数字是同一个数字的正数和负数,否则它将始终返回false
例如,如果我有一个数组是[1,4,6,-1,10],它应该返回true。我确信我的2 while语句是造成这一问题的原因,但我想不出解决的办法。如果有人能给我指出正确的方向,那会很有帮助。好吧,鉴于它被标记为ruby,下面是我能想到的解决这个问题的最简单的ruby方法:
def two_sums(arr)
numbers = arr.combination(2).select { |a| a.reduce(:+) == 0 }.flatten
if numbers.empty?
"Nothing adds to zero."
else
"There are 2 numbers that sum to zero & they are #{numbers.first} and #{numbers.last}."
end
end
您可以找到相加为0的第一对,如下所示:
nums.combination(2).find { |x, y| x + y == 0 }
#=> returns the first matching pair or nil
def two_sums(nums)
pair = nums.combination(2).find { |x, y| x + y == 0 }
if pair
"There are 2 numbers that sum to zero & they are #{pair.first} and #{pair.last}."
else
"Nothing adds to zero."
end
end
或者,如果要选择相加为0的所有对:
nums.combination(2).select { |x, y| x + y == 0 }
#=> returns all matching pairs or an empty array
因此,您可以实现如下方法:
nums.combination(2).find { |x, y| x + y == 0 }
#=> returns the first matching pair or nil
def two_sums(nums)
pair = nums.combination(2).find { |x, y| x + y == 0 }
if pair
"There are 2 numbers that sum to zero & they are #{pair.first} and #{pair.last}."
else
"Nothing adds to zero."
end
end
或者,如果要查找所有对:
def two_sums(nums)
pairs = nums.combination(2).select { |x, y| x + y == 0 }
if pairs.empty?
"Nothing adds to zero."
else
"The following pairs sum to zero: #{pairs}..."
end
end
我认为最简单的方法是:
nums.combination(2).any? { |x,y| (x+y).zero? }
这里有一种适合大型阵列的方法。上面的方法通过两个数字的每一个可能的组合,对于小的情况来说都是非常好的,但是对于包含大量元素的数组来说,速度会非常慢,内存会非常紧张
def two_sums nums
h = Hash.new
nums.each do |n|
return true if h[-n]
h[n] = true
end
false
end
还有一种方法:
代码
例子
这种方法比较快。让我们尝试使用200000个元素的数组,每个元素都是-500000到500000之间的随机数
require 'time'
t = Time.now
arr = Array.new(200_000) { rand(1_000_001) - 500_000 }
arr.size #=> 200000
sum_to_zero(arr).size #=> 16439
Time.now - t
#=> 0.23 (seconds)
sum_to_zero(arr).first(6)
#=> [[-98747, 98747],
# [157848, -157848],
# [-459650, 459650],
# [176655, 176655, -176655],
# [282101, -282101],
# [100886, 100886, -100886]]
如果要将总和为零的非负值和负值分组:
sum_to_zero(arr).map { |a| a.partition { |e| e >= 0 } }.first(6)
#=> [[[98747], [-98747]],
# [[157848], [-157848]],
# [[459650], [-459650]],
# [[176655, 176655], [-176655]],
# [[282101], [-282101]],
# [[100886, 100886], [-100886]]]
如果每个组只需要一个非负值的值,请说:
sum_to_zero(arr).map { |a| a.first.abs }.first(6)
#=> [98747, 157848, 459650, 176655, 282101, 100886]
哇,我还是Ruby的新手,所以我能识别90%的代码。还没有达到。减少或。组合。谢谢你的帮助wicz!:因为您知道a是一个两元素数组,所以使用a.reduce:+计算x+y是一种非常复杂的方法。只需选择{| x,y | x+y==0}对于小的情况,这是很好的。但是由于这些方法都在^2上,如果你有大的案例,你会想要一个Onlogn或On方法,你绝对是对的@JKillian。首先对数组进行排序,并让数组两端的指针查找匹配对,这样会更有效。但在我看来,这个问题是关于使代码工作和可读性,而不是关于改进运行时。同意,您的答案适用于大多数情况。为了好玩和提高理论效率,我发布了一个使用哈希的答案。我觉得这段代码非常难看!有没有办法让它看起来更漂亮,但功能却保持不变?非常好!我修改它以返回满足求和为零要求的所有n>=0,并对我在回答中给出的200000个元素的随机数组运行它。它是闪电般的快!代码如下:h={};nums.each|u with|u object[]{n,a | h[n]=true;a[361248,209826,277499,32486156859,112086]。使其需要'set';nums.each|u with|objectSet.new{n,s|h[n]=true;s整洁的方法,我认为这也应该是线性时间,因为group_by应该是线性的,而.uniq应该只需要遍历每个值一次,所以也应该是线性时间。就像一个小小的吹毛求疵一样,我相信a.size>1条件在主方法中是多余的definition@JKillan,我们必须确保uded,包含零的数组的大小必须至少为2。但是,我所做的可以改进,我已经做了修复。谢谢您的提醒。
array.combination(2).select{|x|x[0] + x[1] == 0}