如何将一组集合减少到没有元素是另一个元素的子集?

时间:2015-01-24 02:33:16

标签: algorithm set-theory

首先:不,这不是功课!这适合我为游戏写作的解算器。我只是将问题简化为这个简洁的陈述:

给定一组S,找到并删除S的任何元素,这些元素是S的其他元素的子集。

1< = | S | < = C ^ K

1< = | S i | < = K

2 <= C <= 10

10 <= K <= 500

详细

S i 是[0,K)

的子集

min(| S i |)&gt; = log C (| S |)

我目前的方法是将每个集合保存在S中,通过我称之为&#34; NatSet&#34;这只是bool[K]。然后我通过| S i |对S进行排序并执行O(| S | ^ 2)搜索以查找作为其他元素子集的元素。不幸的是,这对我的目标值C = 6和K = 16 * 9来说太慢了。

2 个答案:

答案 0 :(得分:2)

考虑到我无法尝试(set S的输入对我来说是不可见的)并决定以下是否有用,我只能给他们一些提示:

  1. 比较两套:&#39;缩小&#39; binary search:当你比较集合A(x1 ... xn)是否是集合B的子集(y1 ... ym)时,假设你找到yk = x1(n <= m)

        y1, y2, ...,yk, yk+1 ... ym
                    |
                   x1   
    

    然后您可以在x2范围内搜索[yk+1, ym]。另一个是相同的。

  2. 选择两组进行比较时: 选择大一个(即s1sk,然后s1sk-1),你说你按大小排序,大一个更有可能包含它
  3. 排序Si?我不确定排序S是否可以提高您的效果,您可以尝试不排序或使用max-heap(参见提示4)
  4. 使用max-heap: 比较叶子与root和root的一个儿子...... 如图表所示)。
  5. enter image description here

    如果没有移除叶子(即,不是它的父亲的子集),只需将其从堆中移除即可将其交换到移除叶子的位置。 (如下图所示)

    enter image description here

    注意:使用堆不能保证删除所有子集。

    1. 如何排序?:在您的情况下,似乎counting sort是一种合适的排序方式,即线性排序。
    2. 更多

      1.你说你正在砍树,你想要Alpha–beta pruning吗?

      2。Efficient list intersection algorithm

      希望这会有所帮助。

答案 1 :(得分:0)

这里固有的问题是,给定两个集合,一个具有p个元素,另一个具有q个元素(不失一般性,我们可以说p

根据我的理解,你正在进行O(K ^ 2)搜索,所以你得到总的运行O((n ^ 2)*(K ^ 2)),其中n是S的元素数量你可以使用HashSet方法将它减少到O((n ^ 2)K)。这里是Java http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html的链接,几乎所有主要语言都在其标准库中有一些实现。虽然如果你的集合S在n = 6 ^(16 * 9)附近,那么我认为这不会有多大帮助(我甚至不确定你是否可以在现代计算机中使用任何相关数据尺寸)。

如果你可以将k驱动到&lt; = 64(或32位系统中的32),你可以使用位图来存储S中的每个集合和并行位操作,以将你的时间减少到O(n ^ 2)。这将等同于您当前的方法,但您只需执行一次或检查它是否等于相同的数字:((a1 | a2)== a1)|| ((a1 | a2)== a2)。这样您就可以在恒定时间内获得并集操作。