【问题标题】:Finding a particular Set of SubSets of a PowerSet in an efficient way以有效的方式查找 PowerSet 的特定子集集
【发布时间】:2011-09-23 04:08:53
【问题描述】:

我正在尝试找到一种有效的方法来获取 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} 的幂集:

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

【问题讨论】:

  • 您要求一种有效的算法来计算 P(A) - P(B) where B ⊆ A?
  • @JohnKugelman 是的,语法似乎正确
  • 我不相信这样有效的算法存在。对于 n 元素,幂集算法的复杂度为 O(2^n),如您所说,指数复杂度对于大输入是不切实际的。
  • 是否有必要在内存中将您的集合作为一个整体来表示,还是对这些集合进行足够的枚举?
  • @jmg 枚举就可以了

标签: java algorithm big-o


【解决方案1】:

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

例如假设 A-B 有一个元素,|P(A)-P(B)| = 2n - 2(n-1) = 2(n-1),例如对于 n = 40 你不能迭代所有项目。

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

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

【讨论】:

    【解决方案2】:

    尝试另一种方式:

    调用 set3 = set - set2;

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

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

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

    Hth.

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        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(n2) 对于 HashSet

        现在您可以调用removePowerSet(sets, set2)removePowerSet(sets, Arrays.asList(3)) 来获取示例中的结果。

        【讨论】:

        • 感谢您的回复,我明天早上会玩这个。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-30
        • 1970-01-01
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        相关资源
        最近更新 更多