查找与数字对应的数字集

时间:2014-07-03 13:17:59

标签: ruby

从一个数字,我想生成不同的数字组,其中总和对应于这个数字。

示例:

generate_groups([], 1) would be equal to [ [1] ]
generate_groups([], 2) would be equal to [ [1,1] , [2] ]
generate_groups([], 3) would be equal to [ [1, 1, 1], [1, 2], [2, 1], [3] ]

我已经在迭代代码中编写了解决方案,但在递归方面有更好的答案。

所以,我写了下面的代码:

def generate_groups(combo = [], rest)
  return combo.flatten if rest <= 0

  result = []
  (1..rest).each do |number|
    combo << number
    tmp_res = generate_groups(combo, rest-number)
    result << tmp_res
    combo.pop
  end
  return result
end

但它不好,因为它在数组中生成数组。 例如,generate_groups([], 3)是:

[ [ [ [1, 1, 1] ], [1, 2] ] , [ [2, 1] ] , [3] ]

我的算法出了什么问题?

1 个答案:

答案 0 :(得分:2)

您的解决方案可以像这样修复:

def generate_groups(combo = [], rest)
  return [combo.dup] if rest <= 0  # no need for flattening 

  result = []
  (1..rest).each do |number|
    combo << number
    tmp_res = generate_groups(combo, rest-number)
    result += tmp_res # concat the solutions instead of nesting them.
    combo.pop
  end
  return result
end

dup是必要的,否则稍后会通过更改combo来更改固定结果。您的flatten也创建了该阵列的副本。

但是,通过递归传递内部状态(combo)看起来很奇怪。这不是必需的。我的建议

def generate_groups(rest)
  return [[]] if rest <= 0

  (1..rest).inject([]) do | a, number |
    a + generate_groups(rest - number).map { | g | g << number }
  end
end

使用inject,我连接中间结果数组。