以有效的方式查找PowerSet的一组特定子集

时间:2011-09-23 04:08:53

标签: java algorithm big-o

我正在尝试找到一种高效方式来获取PowerSet的一组子集。

例如,当设置的尺寸较小时,这种方法有效:

Set<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);

Set<Integer> set2 = new HashSet<Integer>();
set2.add(3);


Set<Set<Integer>> sets = MyUtils.powerSet(set); //size - 8 SubSets
Set<Set<Integer>> badSets = MyUtils.powerSet(set2); //size - 2 SubSets

//my set of subsets of the powerset
sets.removeAll(badSets) //size - 6 SubSets

然而,当将更多元素添加到这些集合中时,这变得不实用。还有另一种方法吗?

简单友好地提醒一下PowerSet是什么:

{a,b,c}的PowerSet:

P(S)= {{},{a},{b},{c},{a,b},{a,c},{b,c},{a,b,c}}

4 个答案:

答案 0 :(得分:3)

如果从P(A)中移除P(B)后,一组是另一组(A,B大小为m,n)的子集,则有2 n - 2 m 元素,如果B不是A的子集,也可以假设B'=A intersection with B并且我们也有类似的关系,所以数字总是很大。

例如,假设A-B具有一个元素,| P(A)-P(B)| = 2 n - 2 (n-1) = 2 (n-1),例如对于n = 40,您无法迭代超过所有项目。

无论如何,一种方式如下:

在基数2中有一个大小为n的计数器,首先将m + 1位设置为1,将所有其他设置为0然后打印结果,并且每次增加计数器(按1)并打印结果达到2 n - 1 。这是O(2 n - 2 m )。

答案 1 :(得分:1)

尝试另一种方式:

让我们调用set3 = set - set2;

然后Powerset(设定) - Poserset(set2)= Powerset(set3)x(Powerset(set) - {});

其中x这里是2个集的笛卡尔倍数。

如果set3有x元素,set2有y元素,那么使用这种方法,它的复杂度约为2 ^(x + y),而如果尝试直接删除它,则复杂度约为2 ^(x + 2Y)。

H个。

答案 2 :(得分:1)

听起来像零抑制决策图的工作。它们支持set-subtraction,并且在ZDD中创建一系列数字的powerset是微不足道的(事实上,生成的ZDD具有非常少的节点)。这意味着非对称差异也会快速运行,因为它位于两个小的ZDD上,它只取决于节点中ZDD的大小,而不是它们包含的集合数量的大小。我不知道你接下来要做什么,但不管它是什么,你总是可以枚举ZDD中的所有集合并将它们放在其他数据结构中。

答案 3 :(得分:0)

为了从另一个中减去一个幂集,扣除的功率集计算是多余的。这是要走的路:

public static <T>void removePowerSet(
        Collection <? extends Collection <T>> powerSet,
        Collection <T> removedComponents){
    Iterator <? extends Collection <T>> powerSetIter = powerSet.iterator();
    while (powerSetIter.hasNext()) {
        Collection <T> powerSetSubset = powerSetIter.next();
        if (removedComponents.containsAll(powerSetSubset)) {
            powerSetIter.remove();
        }
    }
}

此算法在多项式时间内执行 - O(n 2 )表示HashSet

现在,您可以致电removePowerSet(sets, set2)removePowerSet(sets, Arrays.asList(3))以获得示例中的结果。