我应该怎么写这个方法?

时间:2015-07-22 18:35:08

标签: ruby methods

问题的提示是:

  

编写一个采用数组数组的方法。如果数组中的一对数字总和为零,则返回这两个数字的位置。如果没有数字对总和为零,则返回nil

我不确定如何解决这个问题以及最简单的方法。这会涉及.index方法吗?

def two_sum(nums)
end

two_sum([1,3,5,-3])

4 个答案:

答案 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

这里的细分有点复杂。如果您想了解它,我建议您在ArrayEnumerable上查看这些方法的文档。

答案 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`