我有一个数组,其长度为X
。数组的每个元素都有范围1 .. L
。我想有效地迭代所有具有总和L
的数组合。
正确的解决方案:L = 4且X = 2
1 3
3 1
2 2
正确的解决方案:L = 5且X = 3
1 1 3
1 3 1
3 1 1
1 2 2
2 1 2
2 2 1
天真的实现(难怪)对我的问题来说太慢了(在我的情况下X最多为8,L最多为128)。
有人能告诉我这个问题是如何调用的,或者在哪里找到问题的快速算法?
谢谢!
答案 0 :(得分:8)
如果我理解正确,你会得到两个数字1≤ X ≤ L 你想要生成长度为 X <的所有正整数序列/ em>总和为 L 。
(注意:这类似于integer partition problem,但不一样,因为您认为1,2,2是与2,1,2不同的序列,而在整数分区问题中我们忽略顺序,以便这些被认为是相同的分区。)
您要查找的序列对应于 X 的combinations - L 中的1项 - 1.因为,如果我们输入数字按顺序1到 L - 1,并选择 X - 其中1个,然后所选数字之间的间隔长度为正整数,总和为 L < / em>的
例如,假设 L 为16且 X 为5.然后选择1到15之间的4个数字:
在开头添加0,在结尾添加16,间隔为:
根据需要
和3 + 4 + 1 + 6 + 2 = 16.
X 的generate the combinations - L - 1中的1项,并且对于每一项,通过查找间隔将其转换为分区。例如,在Python中你可以写:
from itertools import combinations
def partitions(n, t):
"""
Generate the sequences of `n` positive integers that sum to `t`.
"""
assert(1 <= n <= t)
def intervals(c):
last = 0
for i in c:
yield i - last
last = i
yield t - last
for c in combinations(range(1, t), n - 1):
yield tuple(intervals(c))
>>> list(partitions(2, 4))
[(1, 3), (2, 2), (3, 1)]
>>> list(partitions(3, 5))
[(1, 1, 3), (1, 2, 2), (1, 3, 1), (2, 1, 2), (2, 2, 1), (3, 1, 1)]
有( L - 1)! /( X - 1)!( L - X )! X 的组合 - L - 1中的1项,因此该算法的运行时间(及其输出的大小)在 L 。但是,如果不计算输出,则只需要O( L )空间。
L = 128且 X = 8,有89,356,415,775个分区,所以输出它们需要一段时间!
(也许如果你解释为什么要计算这些分区,我们或许可以建议一些满足你需求的方法,而不必实际生成它们。)