从一组集合中找到集合子集的最佳方法
Best way to find a subset of a set from a group of sets
首先,很抱歉标题不明确。
假设我有以下一组集合:
第1组
s1 = ( x1, y1 )
s2 = ( x2 )
第2组
m1 = ( x1, y1, y2 )
m2 = ( x1 )
m3 = ( x1 , x2 )
对于Group 1
中的每个集合——称之为集合s
,我需要找到Group 2
中的集合——称其为m
——使得m
是s
的子集。
因此,以我为例,答案是:
s1 -> m2
s2 -> nothing
目前,我将这些值存储在std:set
中,但如果需要,我可以更改它。此外,集合可能会变大,因此算法需要高效。目前,我有一种蛮力的方法,但我并不完全满意。
有什么建议吗?
第一步是根据基数(即大小)对组1进行排序。那么算法的顺序是:
foreach std::set M in "Group 2" {
foreach std::set S in "Group 1" and S.size()>=M.size() { // replace with binary search
if ( std::includes(S.begin(),S.end(),M.begin(),M.end()) )
{ /* M is a subset of S */ }
}
}
}
这应该具有时间复杂性~O(MSR),其中M是"第2组"中的集合数,S是"第1组"中集合数,R是"第#1组"中最大集合的大小。
编辑:我刚刚想到,使用S.find()
而不是调用std::includes()
(按顺序迭代)可能更有效,但我认为只有当M.size()比S.size()小得多时,情况才会如此——O(M+S)vs O(MlogS)。
您并不清楚您的方法有多暴力。只要您在std::命名空间中使用集合查询函数,它们就可能尽可能高效。例如,测试set_interaction(s1.begin(),s2.end(),m1.begin),m1.end(())是否等价于m1。
您可以比这更高效,因为您不需要匹配元素的副本,只需要知道它们都出现了。这可以通过复制set_interaction的代码来实现,但要更改实现,只需计算匹配元素的数量,而不是将它们复制出去。那么,如果计数与m的大小相同,那么你就有了匹配项。
至于容器,我通常更喜欢排序的deque,而不是大型集合的集合。内存在堆上的分布要少得多,这有助于缓存。它还避免了底层树的开销。当容器只创建了一次,但被搜索了多次时,这尤其有益。
您的集合是经常修改的还是只读的?
- 如果经常修改,
std::set
是修改和排序性能之间的良好平衡 - 如果是只读或只读,则可以使用排序的
std::vector
。排序是昂贵的,但实际上比在std::set
中构建一整棵树更便宜,所以如果很少这样做,性能会更好
一旦您制作了排序的容器(无论是"自动排序"的std::set
还是手动排序的std::vector
),您就可以使用std::includes
测试子集。顺便说一句,如果你需要找到合适的子集,你可以在之后比较元素计数。
您可以尝试这样的方法。步骤:
- 创建一个包含两个组中所有对象的数组
- 转换位数组中的每个s和m,其中,如果集合包含对象(i),则数组(i)=1,否则为0
- 如果m(k)AND s(j)=m(k
- 处理多个异常集合的C++方法
- 给定n个元素的m个集合.在C++中找到出现在最大集合数中的元素
- 如何将ampl中的集合表示为c++中的向量
- 显示字符串的集合和子集
- 在尝试使用递归查找集合子集的总数时,我遇到了分割错误
- 打印给定大小的集合的所有子集并计算子集
- 给定一组正整数 <=k 及其 n 个子集,找到哪些子集对给出原始集合的并集
- (也许是NP-Hard)求一个集合的子集总数,使得每个子集在与其所有元素相乘时的值都大于X
- 如何生成集合的所有唯一子集
- 动态规划:计算集合中存在多少个升序子集
- 递归函数,用于使用位掩码 c++ 显示集合的所有子集
- 拘泥于处理(数学)集合和子集的练习
- 生成给定集合的子集(使用递归)的程序的执行涉及哪些步骤
- 用于访问集合c++的排序子集的数据结构
- 一个多索引,其中一个索引是整个集合的子集
- 从一组集合中找到集合子集的最佳方法
- 使用0来显示不存在元素的集合的子集
- 从一个集合生成所有可能的有序子集
- 如何将一个集合分成K个子集,使得子集中元素的和最小
- 生成一个集合的所有子集,使它们的集合等于整个集合