基本上,我有一个包含25个不同人的数组,我需要选择其中5个人,并且每个组合都可以,而不使用同一个人的副本。
我能想到的唯一合乎逻辑的方法是使用5个for循环并检查是否已经使用过人,尽管看起来似乎有一个更好的方法涉及递归。
如果有人可以提供帮助,我将非常感激。
以下是我班级的一个例子;
public class Calculator {
final Person[] people = new Person[25]; //Pretend we have filled in this info already
public List<Group> generateList()
{
final List<Group> possible = new ArrayList<>();
for (int a = 0; a < 25; a++)
{
for (int b = 0; b < 25; b++)
{
for (int c = 0; c < 25; c++)
{
for (int d = 0; d < 25; d++)
{
for (int e = 0; e < 25; e++)
{
final Group next = new Group();
next.set = new Person[] {
people[a],
people[b],
people[c],
people[d],
people[e]
};
possible.add(next);
}
}
}
}
}
return possible;
}
class Group {
Person[] set = new Person[5];
}
class Person {
String name;
int age;
}
}
然而,我不确定这样做的最好方法,如果这样就能得到所有组合。我也知道这里没有重复检查,我通过检查来做;
如果(b == a)继续;
等
我将不胜感激。
答案 0 :(得分:9)
一种可能性是使用组合库,如:http://code.google.com/p/combinatoricslib/。
// Create the initial vector
ICombinatoricsVector<String> initialVector = Factory.createVector(
new String[] { "red", "black", "white", "green", "blue" } );
// Create a simple combination generator to generate 3-combinations of the initial vector
Generator<String> gen = Factory.createSimpleCombinationGenerator(initialVector, 3);
// Print all possible combinations
for (ICombinatoricsVector<String> combination : gen) {
System.out.println(combination);
}
示例来自项目页面(参见链接)。将它转移到您的用例应该很容易。
答案 1 :(得分:2)
有很多选择。
(1)
你可以使用
改善你的算法for a = 0 to 25
for b = a+1 to 25 // use ascending-order rule
for c = b+1 to 25
等 - 这消除了重复检查,利用了问题的因子性质
(2)
您也可以将这些作为整个N ^ R项目的单个for循环实现(如果您从N中选择R项目),并丢弃不完全升序的排列。如果您事先不知道R,这很好。想象一下,你在基数N
for i = 0 to N^R // count in base N
for digit = 0 to R
value[digit] = (i/N^digit) mod (N^(digit+1)) // extract the required digit
if digit>0 && value[digit]<value[digit-1], SKIP
换句话说,你按顺序计算这些R指数。
(3)
最后一个选项,即代码更长但对大R和N更有效,是使用一组索引:
// i is an array size R, with items ranging from 0 to N
i = int[]{ 0, 1, 2, 3, 4 }; // each is an index of the items in N
while !finished
j=0; // index to start incrementing at
i[j] ++;
然后,如果您在任何索引上超过N
,请增加j
,增加i[j]
,并将所有i[k<j]
设置为[0 1 2 ... j-1]
,然后开始计算再次!
这通过所有组合最有效地循环。