来自30个对象列表的4个唯一对象的每个集合和子集?

时间:2015-10-14 10:43:50

标签: java pseudocode

我无法制作算法,该算法从~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个对象(而我需要子元素少的元素)。

谷歌搜索这个问题产生了很多答案,但从来没有产生所有子集的答案,并且对集合的大小有限制。

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;

这不是一个非常聪明的解决方案,但它确实有效。