Algorithm 为具有重复项的列表生成所有组合
与之相关,我想知道为一个总共包含Algorithm 为具有重复项的列表生成所有组合,algorithm,combinations,Algorithm,Combinations,与之相关,我想知道为一个总共包含m元素的列表生成r元素的所有组合的算法(以及java/c/c++/python/等中的实际代码,如果有的话!)。其中一些m元素可能会重复 谢谢 针对每种元素类型递归 int recurseMe(list<list<item>> items, int r, list<item> container) { if (r == container.length) { //print out your collection
m
元素的列表生成r
元素的所有组合的算法(以及java/c/c++/python/等中的实际代码,如果有的话!)。其中一些m
元素可能会重复
谢谢 针对每种元素类型递归
int recurseMe(list<list<item>> items, int r, list<item> container)
{
if (r == container.length)
{
//print out your collection;
return 1;
}
else if (container.length > score)
{
return 0;
}
list<item> firstType = items[0];
int score = 0;
for(int i = 0; i < firstType.length; i++)
{
score += recurseMe(items without items[0], r, container + i items from firstType);
}
return score;
}
int recurseMe(列表项、int r、列表容器)
{
if(r==container.length)
{
//打印出你的收藏;
返回1;
}
else if(container.length>score)
{
返回0;
}
list firstType=项目[0];
智力得分=0;
for(int i=0;i
这需要一个包含项目列表的列表作为输入,假设每个内部列表表示一种唯一的项目类型。您可能需要构建一个排序函数,以作为输入提供给此函数
//start with a list<item> original;
list<list<item>> grouped = new list<list<item>>();
list<item> sorted = original.sort();//use whichever method for this
list<item> temp = null;
item current = null;
for(int x = 0; x < original.length; x++)
if (sorted[x] == current)
{
temp.add(current);
}
else
{
if (temp != null && temp.isNotEmpty)
grouped.add(temp);
temp = new list<item>();
temp.add(sorted[x]);
}
}
if (temp != null && temp.isNotEmpty)
grouped.add(temp);
//grouped is the result
//从原始列表开始;
列表分组=新列表();
list sorted=original.sort()//使用哪种方法进行此操作
列表温度=空;
项目当前=空;
对于(int x=0;x
这将对列表进行排序,然后创建包含相同元素的子列表,将它们插入到列表的列表中
分组我将给出一个答案,而不是一堆注释
我最初的评论是:
CombinationGeneratorJava类系统地生成所有
n个元素的组合,一次取r。算法是
Kenneth H.Rosen描述的离散数学及其应用
应用,第二版(纽约:麦格劳·希尔,1991),第284-286页。“见
merriampark.com/comb.htm。它有一个到源代码的链接
正如您在评论中指出的,您需要独特的组合。因此,给定数组[“a”、“a”、“b”、“b”]
,您希望它生成aab,abb
。我链接的代码生成aab,aab,baa,baa
使用该数组,删除重复项非常容易。根据您的实现方式,您可以让它生成重复项,然后在事后对其进行过滤(即从数组中选择唯一的元素),或者修改代码以包含哈希表,以便在生成组合时,在将项放入输出数组之前检查哈希表
在哈希表中查找某个内容是一个O(1)
操作,因此这两个操作中的任何一个都将是有效的。在事后执行此操作的成本会稍高一些,因为您必须复制项。不过,您所说的是O(n)
,其中n
是生成的组合数
有一个复杂问题:顺序是不相关的。也就是说,给定数组[“a”、“b”、“a”、“b”]
,代码将生成aba、abb、aab、bab
。在这种情况下,aba
和aab
是重复的组合,就像abb
和bab
一样,使用哈希表不会为您删除这些重复项。不过,您可以为每个组合创建位掩码,并使用哈希表的思想使用位掩码。这会稍微复杂一点,但不是非常复杂
如果您首先对初始数组进行排序,使重复项相邻,那么问题就会消失,您可以使用哈希表的思想
毫无疑问,有一种方法可以修改代码以防止其生成重复代码。我可以看到一种可能的方法,但它会很混乱且昂贵。这可能会使算法比仅使用哈希表的想法慢。我将采取的方法是:
Sort the input array
Use the linked code to generate the combinations
Use a hash table or some other code to select unique items.
虽然…我有一个想法
如果对输入数组进行排序,则生成的任何重复项都是相邻的,这是真的吗?也就是说,给定输入数组[“a”、“a”、“b”、“b”]
,则生成的输出将按该顺序为aab、aab、abb、abb
。当然,这将取决于实现。但如果在您的实现中是真的,那么修改算法以删除重复项只需检查当前组合是否与前一个相同。这里是一个递归我相信这和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])
使用:
如果组合值(其长度)的总和等于k
,则返回该组合,否则返回一个空集。(+c
是加[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
@Jean Bernard:combination vs.permutation!”CombinationGenerator Java类系统地生成n个元素的所有组合,每次取r。该算法由Kenneth H.Rosen描述,《离散数学及其应用》,第二版(纽约:McGraw-Hill,1991),第284-286页。“参见。它有一个到源代码的链接。@JimMischel:这不是我想要的。对于字符串[]el
{{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}}
f[k_, {}, c__] := If[+c == k, {{c}}, {}]
f[k_, {x_, r___}, c___] := Join @@ (f[k, {r}, c, #] & /@ 0~Range~Min[x, k - +c])