找到一对没有交叉的对

时间:2014-01-15 19:42:43

标签: python algorithm big-o time-complexity

给定一组n对整数,有一种快速的方法来确定是否存在两对(x 1 ,y 1 )和(x 2 ,y 2 )以便集合{x 1 ,y 1 }和{x 2 ,x 2 }是空的吗?

例如,{(0,1),(0,2),(2,1),(3,2)}有{(0,1),(3,2)}作为答案。但是{(0,1),(0,2),(2,1)}没有这样的一对。

在Python中,您可以按如下方式尝试所有对。

l = [(0,1), (0,2), (2,1), (3,2)]
print  [pairs for pairs in itertools.combinations(l, 2)
    if not (set(pairs[0]) & set(pairs[1]))]

这种方法需要O(n 2 )时间。你能得到更接近线性时间的东西吗?

2 个答案:

答案 0 :(得分:5)

以下算法应该在O(n)时间内起作用。它基于以下观察:如果你有一对{a,b},那么每隔一对

  1. 不包括a或b,或
  2. 至少包括a或b中的一个。
  3. 如果您选择任何一组{a,b}并将彼此分组分类为这五个类别中的一个,请注意,如果您在案例1中得到任何内容,那么您已完成并且您知道存在这样的一对。因此,唯一有趣的情况是,当每一其他组分为二的情况下发生这种情况时,我们可以称之为两组“A”组和“B”组(用于匹配,设置和匹配B设定)。

    一旦你的A组和B组,你知道,没有两个A集可以是你想要的对,没有两个B集可以是想要的对,并且集合{A,B}不能成为你想要的一对的一部分。唯一的选择是你可以从A组中取出一些东西并将它与B组中的东西配对。只有当A组中的某些非A组件与B组中的任何非B组件不匹配时,才会发生这种情况。可以通过建立一个哈希表保持所述A基团的非A组分,然后检查所述组B其非B分量是否在哈希集合中的每个元素在O(n)的检查。

    总结一下,算法是

    • 选择一对{a,b}。
    • 对于每对{c,d}:
      • 如果{a,b}和{c,d}不相交,那么就完成了。
      • 否则,如果{a,b} = {c,d},请丢弃{c,d}。
      • 否则,将{c,d}放入A组(如果包含A组或B组)(如果包含b)。
    • 如果A组或B组为空,则不存在对。返回false。
    • 对于A组的每个元素,将该对的非a组件添加到哈希集。
    • 如果B组中的任何元素的非b组件不在哈希集中,则返回true,否则返回false。

    这在时间O(n)中运行并使用O(n)额外的内存。

    希望这有帮助!

答案 1 :(得分:2)

在阅读阅读 templatetypedef answer之前。

我个人会在没有回答他的答案的情况下亲自追捕这个答案,因为做了所有的工作


这是({3}}中定义的算法的一个(不言自明的)python实现:

def exists_pair(seq):
    if len(seq) < 2:
        return False
    a, b = seq[0]  # could be: seq.pop() if modifications are allowed
    a_group = set()
    b_group = set()
    for c, d in seq:
        if not ({a,b} & {c,d}):
            return True
        elif {a,b} == {c,d}:
            continue
        elif a in {c,d}:
            a_group.add(c if c != a else d)
        else:
            b_group.add(c if c != b else d)

    if not a_group:
        return False

    # b_group - a_group: elements of b_group that do not appear in a_group
    return bool(b_group - a_group)

无需检查空b_group,因为b_group - a_group的结果始终是b_group的子集。如果b_group为空,则结果将始终为空,bool为空setFalse,这是正确的。