我无法制作算法,该算法从~30个对象的列表中生成每个集合和子集(包括空集),每个最多包含4个对象集。
我用Java编写它,但伪代码应该没问题。
这是我到目前为止所做的:
for (int a = 0; a < Objects.length; a++) {
for (int b = a + 1; b < Objects.length; b++) {
for (int c = b + 1; c < Objects.length; c++) {
for (int d = c + 1; d < Objects.length; d++) {
// add Objects[a, b, c, d] to the Set
// do other stuff
}
}
}
}
但显然这不起作用,因为它在每组中强制4个对象(而我需要子元素少的元素)。
谷歌搜索这个问题产生了很多答案,但从来没有产生所有子集的答案,并且对集合的大小有限制。
答案 0 :(得分:3)
这应该可以解决问题:
// add the empty set []
for (int a = 0; a < Objects.length; a++) {
// add the set containing (Objects[a])
for (int b = a + 1; b < Objects.length; b++) {
// add the set containing (Objects[a], Objects[b])
for (int c = b + 1; c < Objects.length; c++) {
// add the set containing (Objects[a], Objects[b], Object[c])
for (int d = c + 1; d < Objects.length; d++) {
// add the set containing (Objects[a], Objects[b], Object[c], Object[d])
}
}
}
}
答案 1 :(得分:2)
如果您可以使用Google Guava library,那么使用Sets.powerSet
方法和Java 8将起作用:
Set<Integer> original = ...;
Set<Set<Integer>> result =
Sets.powerSet(original).stream()
.filter(s -> s.size() <= 4)
.collect(Collectors.toSet());
正如链接文档中所述,只要原始集的大小小于或等于30,这就有效。还值得一提的是:
性能说明:虽然大小为n的集合的幂集大小为2 ^ n,但其内存使用量仅为O(n)。构建电源组时,仅复制输入集。只有在迭代功率集时才创建单个子集,并且这些子集本身仅占用少量恒定的内存。
答案 2 :(得分:2)
出于好奇,我想出了一种使用位模式的算法,并且(理论上)并不是每个子集中最多4个对象。但是,由于int
s(32位)的大小,以下Java代码限制为30个对象。我知道这种方法导致O(2 ^ n)的运行时复杂度相当蹩脚(我不推荐它用于生产),但我有点喜欢这个想法: - )
int minSize = 0; // min subset size
int maxSize = 4; // max subset size
int[] a = IntStream.range(0, 30).toArray(); // generate test data
// maximum number of subsets 2^n
int nSubsets = 1 << a.length;
// subsets container
// initial size could be calculated e.g.:
// 30!/(4!*26!) + 30!/(3!*27!) + ... + 1
List<int[]> subsets = new ArrayList<>();
// iterate through all possible patterns 0..2^n
for (int mask = 0; mask < nSubsets; mask++) {
// bitCount should be very fast on most cpus i think
int bitCount = Long.bitCount(mask);
if (bitCount >= minSize && bitCount <= maxSize) {
int[] subset = new int[bitCount];
for (int i = 0, j = 0; i < a.length; i++) {
// add element if bit is set at i
if ((mask & (1 << i)) != 0) {
subset[j++] = a[i];
}
}
subsets.add(subset);
}
}
答案 3 :(得分:0)
我为此做了一个相当不正统的解决方案......
double double1 = 797.5, double2 = 801.2;
这不是一个非常聪明的解决方案,但它确实有效。