【问题标题】:determine if intersection of a set with conjunction of two other sets is empty确定一个集合与其他两个集合的交集是否为空
【发布时间】:2010-04-13 18:31:08
【问题描述】:

对于任何三个给定的集合 A、B 和 C:有没有办法(以编程方式)确定 A 的元素是否是 B 和 C 的合取(编辑:交集)的一部分?

示例:
答:所有大于 3 的数字
B:所有小于 7 的数字
C:所有等于 5 的数字

在这种情况下,集合 A 中有一个元素,即数字 5,它适合。我将其作为规范来实现,所以这个数值范围只是一个例子。 A、B、C 可以是任何东西。

【问题讨论】:

  • 你的集合是整数的子集吗?或者更一般的东西?如果是后者,你如何表示你的集合?
  • @High Performance Mark,它们不代表什么。除非您将规范类视为一种表示形式:martinfowler.com/apsupp/spec.pdf -> 我试图实现部分包含和谷歌搜索等让我想到了集合论。如果我在错误的区域,请告诉我。
  • 我想我正在拼命寻找一些锚点来最终解决一些相关的问题。
  • @Koen:我不明白你打算如何(甚至想不到)在没有程序可访问的表示的情况下以编程方式确定任何事情。
  • 有什么理由不能只计算三个集合的交集并检查它是否为空?

标签: algorithm set specifications set-theory


【解决方案1】:

编辑: 谢谢尼基!

如果B.Count <= C.Count <= A.Count会很有帮助。

D = GetCommonElements(B,C);
if( D.Count>0 && GetCommonElements(D,A).Count >0)
{
    // what you want IS NOT EMPTY
}
else
{
    // what you want IS EMPTY
}

SET GetCommonElements(X,Y)
{
    common = {}
    for x in X:
       if Y.Contains(x):
         common.Add(x);
    return common;
}

Efficient Set Intersection Algorithm


我们可以使用distributive laws of sets

if(HasCommonElements(A,B) || HasCommonElements(A,C))
{
    // what you want IS NOT EMPTY
}
else
{
    // what you want IS EMPTY
}

bool HasCommonElements(X,Y)
{
    // if at least one common element is found return true(immediately)

    return false
}

【讨论】:

  • 除非我弄错了,否则连词本质上是指交集而不是并集。
  • 谢谢尼基!然后问题减少到找到 A ^ B ^ C。
  • @Niki:对我来说这看起来模棱两可,TheMachineCharmer 误解了它,就像我在阅读问题时所做的一样。最好使用确切的术语。
【解决方案2】:

如果我正确理解您的问题,您想以编程方式计算 3 个集合的交集,对吗?你想看看A中是否有一个元素存在于B和C的交集,或者换句话说,你想知道A、B和C的交集是否非空。

许多语言都设置了容器和交集算法,因此您应该能够使用它们。您在 OCaml 中的示例:

module Int = struct
    type t = int
    let compare i j = if i<j then -1 else if i=j then 0 else 1
end;;

module IntSet = Set.Make(Int);;

let a = List.fold_left (fun a b -> IntSet.add b a) IntSet.empty [4;5;6;7;8;9;10];;
let b = List.fold_left (fun a b -> IntSet.add b a) IntSet.empty [0;1;2;3;4;5;6];;
let c = IntSet.add 5 IntSet.empty;;

let aIbIc = IntSet.inter (IntSet.inter b c) a;;
IntSet.is_empty aIbIc;;

这输出 false,因为 a b 和 c 的交集是非空的(包含 5)。这当然依赖于集合的元素是可比较的这一事实(在示例中,函数 compare 在 Int 模块中定义了此属性)。

或者在 C++ 中:

#include<iostream>
#include<set>
#include<algorithm>
#include<iterator>

int main()
{
    std::set<int> A, B, C;

    for(int i=10; i>3; --i)
        A.insert(i);
    for(int i=0; i<7; ++i)
        B.insert(i);
    C.insert(5);

    std::set<int> ABC, BC;
    std::set_intersection(B.begin(), B.end(), C.begin(), C.end(), std::inserter(BC, BC.begin()));
    std::set_intersection(BC.begin(), BC.end(), A.begin(), A.end(), std::inserter(ABC, ABC.begin()));

    for(std::set<int>::iterator i = ABC.begin(); i!=ABC.end(); ++i)
    {
        std::cout << *i << " ";
    }
    std::cout << std::endl;

    return 0;
}

【讨论】:

    【解决方案3】:

    这个问题需要进一步澄清。 首先,您想使用范围给定的符号集吗? 其次,它是一次性问题还是会以某种形式重复(如果是,问题的稳定部分是什么?)?

    如果你想使用范围,那么你可以用二叉树来表示它们,并在这些结构上定义联合和交叉操作。构建树需要 O(n log n),查找结果需要 O(log n)。这不会仅使用树集来获得回报,但它可以灵活地有效地支持任何范围组合(如果您认为“它可以是任何东西”的话)。

    另一方面,如果有任何含义,任何元素集,那么唯一的选择就是枚举元素。在这种情况下,在集合 B 和 C 上构建 B+ 树也需要 O(n log n) 时间,但这里 n 是元素的数量,在第一种情况下,n 是范围的数量。后者可能要大几个数量级,当然它只能表示有限数量的元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 2017-07-12
      • 1970-01-01
      • 2020-03-16
      • 1970-01-01
      相关资源
      最近更新 更多