小编典典

生成具有重复项的列表的所有组合

algorithm

与此问题相关,我想知道算法(如果有的话,还有Java / c / c ++ / python /
etc中的实际代码!)r为列表生成的所有元素组合在一起的元素m总数。其中一些m元素可能会重复。

谢谢!


阅读 287

收藏
2020-07-28

共1个答案

小编典典

我认为这是与 Mathematica中的 Jean-Bernard Pellerin算法紧密相关的递归。

这将输入作为每种类型元素的编号。输出格式类似。例如:

{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}}

要求对此代码进行解释。它是一个递归函数,需要可变数量的参数。第一个参数是k,子集的长度。第二个是要选择的每种类型的计数列表。函数在内部使用第三个参数及其他参数来保存子集(组合),使其得以构造。

因此,当选择集中没有更多项目时,将使用此定义:

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])对于介于0和选择集第一个元素中较小者之间的每个整数,以及k组合总数较少,这是在不超过组合大小的情况下可以选择的最大值k

2020-07-28