三向设置不相交

时间:2013-03-04 01:40:57

标签: algorithm data-structures disjoint-sets

这是我即将进行的测试的练习问题。 我希望得到帮助,找到一个更有效的解决方案来解决这个问题。现在,我知道我可以通过使用3个简单的for循环来解决这类问题,但那将是O(N^3)

此外,我相信以某种方式结合二进制搜索将是最好的方式,并在我正在寻找的答案中给我O(log n)。不幸的是,我有点卡住了。

  

三向集合不相交问题定义如下:给定三组项目, A B C ,如果没有所有三个组共有的元素,则三向不相交,即,没有 x x A,B, C

     

假设 A,B, C 是可以排序的项目集(整数);此外,假设可以在O( n log n )时间内对 n 整数进行排序。给出O( n log n )算法来确定这些集是否为三向设置不相交。

感谢您的帮助

3 个答案:

答案 0 :(得分:4)

问题陈述给出了如何解决问题的明显暗示。假设3组是数学集(元素在每组中是唯一的),只需将3组混合在一起并对它们进行排序,然后线性遍历列表并搜索是否有3个相同项的实例。时间复杂度由排序决定,即O(n log n)。辅助空间复杂度最多为O(n)

另一种解决方案是使用基于散列的地图/字典。只计算3套物品的频率。如果任何项目的频率等于3(这可以在检索频率以进行更新时进行检查),则3组不是3路不相交的。插入,访问和修改可以O(1)摊销的复杂性完成,因此时间复杂度为O(n)。空间复杂度也是O(n)

答案 1 :(得分:2)

如果复杂性是约束(并且空间或常数都不是),则可以在O(n)中求解。创建两个位图,将整数从A映射到第一个,将整数从B映射到第二个。然后遍历第三个(C)直到你耗尽,或者你找到一个条目,其中bitmapA(testInt)和bitmapB(testInt)都被设置。

答案 2 :(得分:0)

我们可以用o(n)来解决这个问题。如果我们使用Set数据结构并考虑初始容量和load factor,则可以这样做。

public static boolean checkThreeWaySetDisjointness(Set<Integer> a, Set<Integer> b, Set<Integer> c)
    {
        int capacity = Math.round((a.size() + b.size()) / 0.75f) + 1;
        Set<Integer> container = new HashSet<Integer>(capacity);
        container.addAll(a);
        for (int element : b)
        {
            if (!container.add(element))
            {
                if (c.contains(element))
                {
                    return false;
                }
            }
        }
        return true;
    }

我们正在创建新的Set容器,因为如果我们开始直接在任何现有的Set a / b / c中添加,一旦达到其实际大小的75%的容量,内部java将创建新的Hashset并复制整个现有的Set它。这种开销将具有O(n)的复杂性。因此,我们在这里创建了大小容量的新HashSet,这将确保不会有复制的开销。然后复制整个Set a,然后继续从Set b中逐个添加元素。在Java中,如果add()返回false,则表示当前集合中已存在元素。如果是,请在第三个集合c中检查相同内容。添加和包含HashSet的方法具有O(1)的复杂性,因此整个代码在O(n)中运行。