我得到一堆2s和3s,我必须在一起。现在我想生成这些数字的每个唯一组合,以便当这些组合相乘时不超过10。
例如,我有类似的东西。
2*2*2*2*3*3*3
我可以从上面获得以下有效组合。
4*4*9*3
8*6*9
4*2*6*9
但以下组合是错误的。 16*3*9
和4*4*27
。
有人建议使用算法吗?
答案 0 :(得分:2)
可以递归地构建解决方案。将输入视为数字列表,例如[2,2,2,2,3,3,3]。将列表分为前缀(例如[2,2])和相应的后缀(在这种情况下为[2,2,3,3,3])。现在多个前缀中的条目(在本例中我们得到4),并递归地解决了后缀的相同问题。将多重性的值插入到后缀的每个解的开头,我们得到原始问题的答案。
在下面的Python代码中,递归逻辑在函数collapse
中定义,它找到所有有效前缀(其多重性小于10)并将多重性插入到折叠剩余数据时返回的所有结果中在删除前缀(collapse(d[prefix_len:])
)之后。
a = [2,2,2,2,3,3,3]
def collapse(d):
if len(d) > 0:
for prefix_len in range(1, len(d) + 1):
prefix = reduce(lambda x,y: x*y, d[:prefix_len], 1)
if prefix > 10:
break
for suffix in collapse(d[prefix_len:]):
yield [prefix] + suffix
else:
yield d
for i in collapse(a):
print i
输出
[2, 2, 2, 2, 3, 3, 3]
[2, 2, 2, 2, 3, 9]
[2, 2, 2, 2, 9, 3]
[2, 2, 2, 6, 3, 3]
[2, 2, 2, 6, 9]
[2, 2, 4, 3, 3, 3]
[2, 2, 4, 3, 9]
[2, 2, 4, 9, 3]
[2, 4, 2, 3, 3, 3]
[2, 4, 2, 3, 9]
[2, 4, 2, 9, 3]
[2, 4, 6, 3, 3]
[2, 4, 6, 9]
[2, 8, 3, 3, 3]
[2, 8, 3, 9]
[2, 8, 9, 3]
[4, 2, 2, 3, 3, 3]
[4, 2, 2, 3, 9]
[4, 2, 2, 9, 3]
[4, 2, 6, 3, 3]
[4, 2, 6, 9]
[4, 4, 3, 3, 3]
[4, 4, 3, 9]
[4, 4, 9, 3]
[8, 2, 3, 3, 3]
[8, 2, 3, 9]
[8, 2, 9, 3]
[8, 6, 3, 3]
[8, 6, 9]
答案 1 :(得分:2)
如果订单很重要(即2 * 4 * 2与2 * 2 * 4不同)并且您必须列出它们(即“生成”),那么您应该以递归方式完成所有操作。在斯卡拉:
def combine(who: List[Int], limit: Int=10): List[List[Int]] = who match {
case x :: y :: more =>
combine(y :: more, limit).map(x :: _) :::
(if (x*y<limit) combine((x*y) :: more, limit) else Nil)
case x :: Nil => List(who)
case Nil => List()
}
你可能不知道Scala,所以这里有三种情况。第一种情况:列表至少剩下两个元素。选择第一个元素并将其添加到所有可能的后续组合中。然后, if 可以合并第一个和第二个元素,这样做,并找到以该开头的列表的所有组合。第二种情况:只有一个元素的简单列表;将其作为列表中的唯一内容返回。第三种情况:退化输入(没有给出值);返回一个空列表。
(在Scala中,:::
将两个列表连接在一起,而x :: list
将x
粘贴在list
的前面。当您匹配时,它会反过来周围:如果列表可以分解为元素case x :: stuff
,则使用x
,其余的stuff
。Nil
是空列表。)
这是在行动:
scala> combine( List(2,2,2,2,3,3,3) )
res18: List[List[Int]] = List(List(2, 2, 2, 2, 3, 3, 3), List(2, 2, 2, 2, 3, 9),
List(2, 2, 2, 2, 9, 3), List(2, 2, 2, 6, 3, 3), List(2, 2, 2, 6, 9),
List(2, 2, 4, 3, 3, 3), List(2, 2, 4, 3, 9), List(2, 2, 4, 9, 3),
List(2, 4, 2, 3, 3, 3), List(2, 4, 2, 3, 9), List(2, 4, 2, 9, 3), List(2, 4, 6, 3, 3),
List(2, 4, 6, 9), List(2, 8, 3, 3, 3), List(2, 8, 3, 9), List(2, 8, 9, 3),
List(4, 2, 2, 3, 3, 3), List(4, 2, 2, 3, 9), List(4, 2, 2, 9, 3), List(4, 2, 6, 3, 3),
List(4, 2, 6, 9), List(4, 4, 3, 3, 3), List(4, 4, 3, 9), List(4, 4, 9, 3),
List(8, 2, 3, 3, 3), List(8, 2, 3, 9), List(8, 2, 9, 3), List(8, 6, 3, 3), List(8, 6, 9))
编辑:如果您只想计算它们,则会使用不同类型的重复。让S(n)
为从n
开始的组合数,让L(n)
为列表中n
项的值。然后
S(i) = S(i+1) +
if (L(i)+L(i+1)<10) S(i+2) +
if (L(i)+...+L(i+2)<10) S(i+3) +
....
所以你从最后一项开始 - 只有一种可能性 - 然后使用这个公式按顺序向后工作。 (如果这是你所追求的,我会编写代码,但希望算法足够清晰。)