假设我有一个30个学生的班级,并希望生成一种可能的方式,将它们划分为5个组(顺序无关紧要)。
我知道如何找到学生的所有组合以单独组成一个小组(http://www.merriampark.com/comb.htm)。通过使用该迭代器和一些递归,我可以找到可能的组合组合的PERMUTATIONS。但是,选择组的顺序不相关,我想尽量缩短执行时间。那么如何找到可能组的唯一组合?
上面的算法使用词典排序来避免生成重复的组合......有没有办法可以在群组而不是对象上使用这个想法?
我很了解Ruby,Java / Python也不太了解。提前感谢任何建议!
答案 0 :(得分:5)
嗯,有(30 C 5 * 25 C 5 * 20 C 5 * 15 C 5 * 10 <子> C 子> 5 * 5 <子> C 子> 5)/ 6! = 30!/(6!* 5! 6 )= 123,378,675,083,039,376个不同的分区,每组30个,每组5个,因此无论使用何种方法,生成它们都需要一些时间。
一般来说,选择这样一个分区的一个好方法是对元素使用一些排序,找到最高的未组合元素的分组,然后对其余元素进行分组。
find_partition = lambda do |elts|
if elts.empty?
[[]]
else
highest = elts.pop
elts.combination(4).map do |others|
find_partition[elts - others].map { |part| part << [highest,*others] }
end.inject(:+)
end
end
find_partition[(1..30).to_a]
这样你只需要生成一次分区
答案 1 :(得分:1)
这是一个老问题,但无论如何,为了记录,这就是我在Ruby中的方式:
class Array
def groups_of_size(n)
Enumerator.new do |yielder|
if self.empty?
yielder.yield([])
else
self.drop(1).combination(n-1).map { |vs| [self.first] + vs }.each do |values|
(self - values).groups_of_size(n).each do |group|
yielder.yield([values] + group)
end
end
end
end
end
end
我使用枚举器,因为输出可以非常快速地增长,严格的输出(例如数组)将没有用。用法示例:
>> pp [0, 1, 2, 3, 4, 5].groups_of_size(3).to_a
=>
[[[0, 1, 2], [3, 4, 5]],
[[0, 1, 3], [2, 4, 5]],
[[0, 1, 4], [2, 3, 5]],
[[0, 1, 5], [2, 3, 4]],
[[0, 2, 3], [1, 4, 5]],
[[0, 2, 4], [1, 3, 5]],
[[0, 2, 5], [1, 3, 4]],
[[0, 3, 4], [1, 2, 5]],
[[0, 3, 5], [1, 2, 4]],
[[0, 4, 5], [1, 2, 3]]]
答案 2 :(得分:0)
您可以对排列进行一些后处理。一些伪代码(用您选择的语言实现......):
// We have a list of lists called 'permutations'
// combinations is an (empty) list of lists
for each permutation in permutations
{
sortedPermutation = permutation.sort()
if (! combinations.find(sortedPermutation) )
{
combinations.add(sortedPermutation);
}
}
可能不是最有效的;我要添加排序&amp;与个人生成排列的代码进行比较。
答案 3 :(得分:0)
一种可能性是找到所有组合以形成单个组,然后通过并生成不包含该组个体成员的组合。类似的东西:
List<List<Student>> combinations=Combinations(students);
public void GenerateCombinations(int startingIndex, List<List<Student>> currentGroups, int groupsLeft)
{
if(groupsLeft==0) ProcessCombination(currentGroups);
for(int i=startingIndex; i<combinations.Count; i++)
{
if combinations[i] does not contain a student in current groups
GenerateCombinations(i+1, currentGroups + combinations[i], groupsLeft -1);
}
}
它不是最有效的方法,但它应该生成所有组的组合。我怀疑如果要生成临时的组合列表,可以获得更好的性能,其中所有不可能发生的组都被删除,但这会更复杂。
稍微一点,应该有来自30名学生的142,506种组合形成一组5.我的&lt; sarcasm&gt;太棒了&lt; / sarcasm&gt;数学技能表明应该有大约10 ^ 17 = 100千万亿组的学生组合(30!/((5!^ 6)* 6!); 30!学生的排序,6组5的排序无关紧要,这6组的订购无关紧要)。你可能会坐在那里等待完成。