一种阵列的方法

时间:2016-04-28 03:45:48

标签: arrays ruby

为此编写方法最简洁明了的方法是什么?

  

给定一个数组a和一个数字n,找到n连续的a元素,其总和最大。

     

返回组中第一个元素的最大总和和索引。

例如,使用a = [1, 1, 1, 1, 1, 1, 1, 2]n = 2, 结果将是总和3和位置6

1 个答案:

答案 0 :(得分:6)

arr = [1,3,2,4,3,5,2,1,3,4,2,5,1]
size = 3

效率低但很漂亮

arr.each_cons(size).with_index.map { |a,i| [a.inject(:+), i] }.max_by(&:first)
  #=> [12, 3]

效率高但是用一根丑陋的棍棒瞎了 1

tot = arr[0,size].inject(:+)
(1..arr.size-size).each_with_object([tot, 0]) do |i, best|
  tot += arr[i+size-1] - arr[i-1]
  best.replace([tot, i]) if tot > best.first
end
  #=> [12, 3]

由漂亮的

执行的步骤
enum0 = arr.each_cons(size)
  #=> #<Enumerator: [1, 3, 2, 4, 3, 5, 2, 1, 3, 4, 2, 5, 1]:each_cons(3)> 
enum1 = enum0.with_index
  #=> #<Enumerator: #<Enumerator: [1, 3, 2, 4, 3, 5, 2, 1, 3, 4, 2, 5, 1]:
  #       each_cons(3)>:with_index> 

仔细检查enum1的上述返回值。你会发现它实际上是一个“复合”枚举器。我们可以看到enum1生成的值,并通过将其转换为数组传递给map

enum1.to_a
  #=> [[[1, 3, 2], 0], [[3, 2, 4], 1], [[2, 4, 3], 2], [[4, 3, 5], 3],
  #    [[3, 5, 2], 4], [[5, 2, 1], 5], [[2, 1, 3], 6], [[1, 3, 4], 7],
  #    [[3, 4, 2], 8], [[4, 2, 5], 9], [[2, 5, 1], 10]] 

继续:

b = enum1.map { |a,i| [a.inject(:+), i] }
  #=> [[6, 0], [9, 1], [9, 2], [12, 3], [10, 4], [8, 5],
  #    [6, 6], [8, 7], [9, 8], [11, 9], [8, 10]] 

注意,由于enum1传递给块的map的第一个元素是[[1, 3, 2], 0],因此两个块变量的分配如下(使用 parallel 多个分配):

a, i = [[1, 3, 2], 0]
  #=> [[1, 3, 2], 0] 
a #=> [1, 3, 2] 
i #=> 0 

并执行块计算:

[a.inject(:+), i]
  #=> [6, 0]

最后,

b.max_by(&:first)
  #=> [12, 3] 

Enumerable#max_by确定

中的最大值
b.map(&:first)
  #=> [6, 9, 9, 12, 10, 8, 6, 8, 9, 11, 8]

由不太漂亮的

执行的步骤
a = arr[0,size]
  #=> [1, 3, 2] 
tot = a.inject(:+)
  #=> 6 
enum = (1..arr.size-size).each_with_object([tot, 0])
  #=> (1..13-3).each_with_object([6, 0])
  #=> #<Enumerator: 1..10:each_with_object([6, 0])> 
enum.to_a
  #=> [[1, [6, 0]], [2, [6, 0]], [3, [6, 0]], [4, [6, 0]], [5, [6, 0]],
  #    [6, [6, 0]], [7, [6, 0]], [8, [6, 0]], [9, [6, 0]], [10, [6, 0]]] 
enum.each do |i, best|
  tot += arr[i+size-1] - arr[i-1]
  best.replace([tot, i]) if tot > best.first
end
  #=> [12, 3]

enum的第一个元素[1, [6, 0]]被传递给块,分配给块变量并执行块计算:

i, best = [1, [6, 0]]
  #=> [1, [6, 0]] 
i #=> 1 
best
  #=> [6, 0] 
tot += arr[i+size-1] - arr[i-1]
  # tot = 6 + arr[1+3-1] - arr[1-1]
  #     = 6 + 4 - 1
  #     = 9 
best.replace([tot, i]) if tot > best.first
  #=> best.replace([9, 1]) if 9 > 6
  #=> [9, 1] 
best
  #=> [9, 1] 

其余的计算方法类似。

1信用Bo Diddley(2:51)