我正在尝试找到一种高效方式来获取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}}
答案 0 :(得分:3)
如果从P(A)中移除P(B)后,一组是另一组(A,B大小为m,n)的子集,则有2 n - 2 m 元素,如果B不是A的子集,也可以假设B'=A intersection with B
并且我们也有类似的关系,所以数字总是很大。
无论如何,一种方式如下:
在基数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))
以获得示例中的结果。