关于this question,我想知道算法(以及java/c/c++/python/etc中的实际代码,如果有的话!)为总共有r
个元素的列表生成m
个元素的所有组合其中一些m
元素可能会重复。
谢谢!
最佳答案
这里有一个递归,我认为它与Jean-Bernard Pellerin的算法,在Mathematica中有密切关系。
这将输入作为每种类型元素的数目。输出形式类似例如:
{a,a,b,b,c,d,d,d,d} -> {2,2,1,4}
功能:
f[k_, {}, c__] := If[+c == k, {{c}}, {}]
f[k_, {x_, r___}, c___] := Join @@ (f[k, {r}, c, #] & /@ 0~Range~Min[x, k - +c])
使用:
f[4, {2, 2, 1, 4}]
{{0, 0, 0, 4}, {0, 0, 1, 3}, {0, 1, 0, 3}, {0, 1, 1, 2}, {0, 2, 0, 2}, {0, 2, 1, 1}, {1, 0, 0, 3}, {1, 0, 1, 2}, {1, 1, 0, 2}, {1, 1, 1, 1}, {1, 2, 0, 1}, {1, 2, 1, 0}, {2, 0, 0, 2}, {2, 0, 1, 1}, {2, 1, 0, 1}, {2, 1, 1, 0}, {2, 2, 0, 0}}
An explanation of this code was requested. It is a recursive function that takes a variable number of arguments. The first argument is k
, length of subset. The second is a list of counts of each type to select from. The third argument and beyond is used internally by the function to hold the subset (combination) as it is constructed.
This definition therefore is used when there are no more items in the selection set:
f[k_, {}, c__] := If[+c == k, {{c}}, {}]
如果组合的值之和(其长度)等于
k
,则返回该组合,否则返回空集。(+c
是Plus[c]
的缩写)否则:
f[k_, {x_, r___}, c___] := Join @@ (f[k, {r}, c, #] & /@ 0~Range~Min[x, k - +c])
从左到右阅读:
Join
用于展平一级嵌套列表,因此结果不是越来越深的张量。f[k, {r}, c, #] &
调用函数,删除选择集的第一个位置(x
),并向组合中添加新元素(#
)。/@ 0 ~Range~ Min[x, k - +c])
对于选择集合的第一个元素的零和较小的整数之间的整数,以及k
更少的组合总和,这是可以在不超过组合大小k
的情况下选择的最大值。