所有相交集的联合

时间:2009-06-08 21:11:47

标签: algorithm set language-agnostic set-intersection set-union

给定具有多个属性的对象列表,我需要找到由所有相交子集的并集创建的集合列表。

具体来说,这些是Person对象,每个对象都有许多属性。我需要根据一些唯一标识符(如SSN,DLN等)创建一个“主”集列表。

例如,如果人员A和人员B具有相同的SSN,则他们创建一个集合i。然后,如果人B和C具有相同的DLN,则他们创建集合ii。人D和E具有相同的SSN但是它(以及所有其他标识符)与人A,B或C的任何标识符都不匹配。在合并所有交叉子集之后,我最终将得到一个具有人A,B,C的集合。还有另一套人D,E。

这是我的解决方案的伪代码。我很好奇是否有人已经提出了一种更有效的方法来合并所有可能的交叉集。请记住,集合之间的链接可以是X人长(即,A匹配B乘SSN,B匹配C乘DLN,C匹配D乘SSN,D匹配E乘以其他标识符将导致一组中的人员A-E)。还假设将在支持集合操作中实现的语言。

bigSetList = array of all of the uniq Sets
fullyTested = false
while (bigSetList.size() > 1) or (fullyTested is false)
    foreach thisSet in bigSetList  order by size desc
        if count(sets that intersect with thisSet) > 0
            newThisSet = thisSet
            intersectingSets = []
            bigSetList.delete(thisSet)
            foreach testSet in bigSetList
                if thisSet.intersects(testSet)
                    newThisSet.addAll(testSet)
                    intersectingSets.push(testSetID)
                end if
            end
            bigSetList.delete(intersectingSets)
            bigSetList.push(newThisSet)
            bigSetList.sort()
            break
        end if
    end foreach
    fullyTested = true  // have looped through every set in the list and found 0 intersect partners
end

5 个答案:

答案 0 :(得分:4)

要扩展原始帖子中的评论,您需要创建一个集合列表,其中给定集合的每个成员至少与该集合中的一个其他成员共享至少一个属性。

天真地,这可以通过找到共享属性的所有对并将迭代地具有相同伙伴的对合并在一起来解决。这将是O(N ^ 3)(N ^ 2用于迭代对,最多N个单独的集合以确定成员资格)。

您还可以将此问题视为确定connected component of a graph,其中每个对象和每个唯一属性值都是一个节点;每个对象将连接到其每个属性值。设置该图表需要线性时间,您可以通过广度或深度优先搜索来确定线性时间内的连通分量。

答案 1 :(得分:0)

我猜你有一个相对较小的Person对象属性(与你正在考虑的Person对象的数量相比)。如果要多次减少遍历Person对象列表,可以使用Person,将其属性放入已知可能连接的列表中,然后转到下一个Person。对于每个连续的Person,您将看到它是否连接到任何先前的连接。如果是,则将其唯一属性添加到可能的连接中。您应该能够在一次传递中处理所有Person对象。您可能在结果中有一些断开连接的集合,因此在创建第一个图表后检查未连接的Person对象可能是值得的。

答案 2 :(得分:0)

所以你的收藏示例可能如下所示:

A { ss |-> 42, dl |-> 123 }
B { ss |-> 42, dl |-> 456 }
C { ss |-> 23, dl |-> 456 }
D { ss |-> 89, dl |-> 789 }
E { ss |-> 89, dl |-> 432 }

然后我建议使用一种算法,通过逐步合并或将每个集合插入到多个集合中来构建多个集合:

迭代1.第一个集合成为唯一的多集合:

{A} { ss |-> [42], dl |-> [123] }

迭代2.将下一个集合合并到第一个集合,因为SSN已经存在:

{A,B} { ss |-> [42], dl |-> [123,456] }

迭代3.再次合并,因为DLN已经存在:

{A,B,C} { ss |-> [23,42], dl |-> [123,456] }

迭代4.插入一个新的多集合,因为没有匹配:

{A,B,C} { ss |-> [23,42], dl |-> [123,456] }
{D}     { ss |-> [89],    dl |-> [789]     }

迭代5.合并第二个多集合,因为SSN在那里:

{A,B,C} { ss |-> [23,42], dl |-> [123,456] }
{D,E}   { ss |-> [89],    dl |-> [432,789] }

因此,在每次迭代(每个集合一次)中,您必须识别所有多个集合,这些集合具有与您正在处理的集合相同的值,并合并 all 这些在一起。

通常,如果有n个集合,每个集合具有恒定的k个属性,则该算法将在时间O(nnk)= O(n 2 )中运行。如果所有属性值都不同,则表示最坏情况的行为。当属性值之间存在更多共享时,插入和确定属性值集合中的成员资格所需的时间(如[23,42])将成为主导因素,因此属性值集应该是有效的。

如果使用optimal disjoint sets,则每个查找或合并操作将以摊销时间O(α(n))运行。

因此,对于每次迭代,最多将有n个多集合(到目前为止尚未合并多集合的情况)。要将新集合集成到多集合中,您必须对每个多集合k集执行查找操作,以标识要合并的所有多集合,这需要时间限制为O(nkα(n)) 。要合并最多k个多集合,这种方式需要O(k 2 α(n))。

因此,对于所有迭代,时间受O(n(nkα(n)+ k 2 α(n)))= O(n(nkα(n)))= O( n 2 kα(n))= O(n 2 α(n))因为k是常数。

因为所有实际用途的α(n)也是常数,所以总时间以O(n 2 )为界。

答案 3 :(得分:0)

while (!people.isEmpty()) {
    Person first = people.get(0);
    people.remove(first);
    Set<Person> set = makeSet(first);
    for (Person person : people) {
        for (Person other : set) {
            if (person.isRelatedTo(other)) {
                set.add(person);
                people.remove(person);
            }
        }
    }
    sets.add(set);
}
for (Set<Person> a : sets) {
    for (Set<Person> b : sets.except(a)) {
        for (Person person : a)
            for (Person other : b) {
                if (person.isRelatedTo(other)) {
                    a.addAll(b);
                    b.clear();
                    sets.remove(b);
                    break;
                }
            }
    }
}

答案 4 :(得分:0)

首先,标识符中是否存在一些固有的层次结构,并且与较高排序的标识符相矛盾的是否会取消较低排序的相同标识符?例如,如果A和B具有相同的SSN,B和C具有相同的DLN,并且C和D具有与A和B的SSN不匹配的相同SSN,这是否意味着有两个组或一个?

假设矛盾并不重要,那么您正在处理等价类,如用户57368(未知Google)所述。对于等价类,人们经常转向Union-find结构。至于如何执行这些联合,它并不是立即微不足道的,因为我假设当A和B具有相同的SSN时你没有直接链接A-B。相反,我们的集合将包含两种元素。每个(attribute type, attribute value) = attribute对都是一个元素。您还有与object s对应的元素。迭代对象的属性列表时,请执行union (object, attribute)

Union-find数据结构的一个重要特征是结果结构代表集合。它可以让你查询“A是什么设置?”如果这还不够,请告诉我们,我们可以改进结果。

但最重要的特性是该算法具有类似于每个联合和查询操作的常量时间行为的东西。