我有一个集合A,它由第一个p正整数(1到p)组成,我给出了这个集合的n个子集。如何找到union上有多少对子集给出原始集A?
当然,这可以通过检查每对的并集的大小来天真地完成,如果它等于p,则union必须构成集合A,但是有更优雅的方式来做到这一点,这会减少时间的复杂性?
c ++中的set_union的时间复杂度为2*(size(set 1) + size(set 2)) - 1
,这对nC2对不利。
答案 0 :(得分:0)
如果我们需要应对最坏情况,那么关于这个问题的一些想法:
我认为在没有任何优化的情况下使用std::bitset
对于此任务就足够了,因为联合操作要快得多。但如果没有,不要使用可变大小的向量,使用简单的p-length 0-1数组/向量或unordered_sets。我不认为没有O(1)查找操作的可变大小向量在最坏情况下会更好。
使用启发式方法最小化子集联合。最简单的启发式方法是检查子集的大小。我们只需要对(A, B)
。
size(A) + size(B) >= p
进行配对
除了启发式方法,我们还可以计算(O(n^2)
)子集中每个数字出现的频率。之后,我们可以按照频率增加的顺序检查某些子集中数字的存在。此外,我们可以排除每个子集中出现的数字。
如果您要修复某个子集A
(例如在外部循环中)并找到包含其他子集的联合,则只能检查那些未出现在set {{ 1}}。如果子集A
足够大,则可以显着减少所需的操作数。
答案 1 :(得分:0)
只是对您的方法进行了改进,而不是二进制搜索,您可以保留一个布尔数组,以确定 O中的某些 x 是否出现在 i 中(1)
例如, 让我们说,在进行输入时,您可以保存阵列 i 的所有外观。意思是,如果 x 出现在数组 i 中,则 isThere [i] [x] 应为true,否则为false。
这可以节省一些时间。