Language agnostic 有效集交点-确定交点是否大于k
我面临一个问题,我必须计算集合中所有对之间的交点。没有一个集合小于一个小常数k,我只关心两个集合的交集是否大于k-1元素。我不需要实际的交叉点,也不需要确切的大小,只需要它是否大于k-1。是否有一些聪明的预处理技巧或一套整洁的求交算法可以用来加快速度 更多有助于回答问题的信息:Language agnostic 有效集交点-确定交点是否大于k,language-agnostic,data-structures,set,intersection,Language Agnostic,Data Structures,Set,Intersection,我面临一个问题,我必须计算集合中所有对之间的交点。没有一个集合小于一个小常数k,我只关心两个集合的交集是否大于k-1元素。我不需要实际的交叉点,也不需要确切的大小,只需要它是否大于k-1。是否有一些聪明的预处理技巧或一套整洁的求交算法可以用来加快速度 更多有助于回答问题的信息: 这些集合表示大型无向稀疏图中的最大团。集合的数量可以是数万或更多,但大多数集合可能很小 集合已排序,每个集合的成员按递增顺序排列。实际上,它们是经过排序的列表——我通过这种方式从底层库中接收它们,以便进行最大的派系搜索
- 这些集合表示大型无向稀疏图中的最大团。集合的数量可以是数万或更多,但大多数集合可能很小
- 集合已排序,每个集合的成员按递增顺序排列。实际上,它们是经过排序的列表——我通过这种方式从底层库中接收它们,以便进行最大的派系搜索
- 对于集合中元素的分布(即它们是否处于紧密的簇中)一无所知
- 大多数集合交叉点可能是空的,因此理想的解决方案是一个聪明的数据结构,它可以帮助我减少集合交叉点的数量
- 创建一个所有集合的列表,按它们的第k个最大元素排序(这很容易找到,因为您已经有了每个集合及其元素的顺序)。把这个列表称为L
- 对于任意两个集合A和B,如果A中的第k个最大元素小于B中的最小元素,则它们的交集中不能有多达k个元素
- 因此,对于每个集合,依次计算其与L的相关部分中的集合的交点
对于所讨论的集合,一个好的选择可能是q=2。然后,关键点就是图形的边,为映射提供了一个可预测的大小。由于大多数集合都是不相交的,因此q=2应该消除很多比较,而不会产生太多额外的开销 以下策略应该非常有效。我已经在很多场合使用过这种方法的变体来交叉升序序列 首先,我假设您有某种优先级队列可用(如果没有,滚动您自己的堆非常容易)。和快速键/值查找(btree、hash等) 话虽如此,这里是一个算法的伪代码,它应该可以非常有效地完成您想要的任务
# Initial setup
sets = array of all sets
intersection_count = key/value lookup with keys = (set_pos, set_pos) and values are counts.
p_queue = priority queue whose elements are (set[0], 0, set_pos), organized by set[0]
# helper function
def process_intersections(current_sets):
for all pairs of current_sets:
if pair in intersection_count:
intersection_count[pair] += 1
else:
intersection_count[pair] = 1
# Find all intersections
current_sets = []
last_element = first element of first thing in p_queue
while p_queue is not empty:
(element, ind, set_pos) = get top element from p_queue
if element != last_element:
process_intersections(current_sets)
last_element = element
current_sets = []
current_sets.append(set_pos)
ind += 1
if ind < len(sets[set_pos]):
add (sets[set_pos][ind], ind, set_pos) to p_queue
# Don't forget the last one!
process_intersections(current_sets)
final answer = []
for (pair, count) in intersection_count.iteritems():
if k-1 < count:
final_answer.append(pair)
#初始设置
集合=所有集合的数组
交叉点计数=键/值查找,键=(设置位置,设置位置),值为计数。
p_queue=优先级队列,其元素为(集合[0],0,集合位置),按集合[0]组织
#辅助函数
def过程_交叉点(当前_集合):
对于所有当前_集对:
如果交叉点中有一对\u计数:
交叉点计数[对]+=1
其他:
交叉点计数[对]=1
#找到所有交叉点
当前_集=[]
last_element=p_队列中第一件事的第一个元素
当p_队列不为空时:
(element,ind,set_pos)=从p_队列中获取顶部元素
如果元素!=最后一个元素:
处理交叉点(当前集合)
最后一个元素=元素
当前_集=[]
当前设置追加(设置位置)
ind+=1
如果ind
运行时间为
O(总和(集合大小)*log(集合数量)+计数(一个点在一对集合中的次数)
。特别要注意的是,如果两个集合没有交集,您就永远不会尝试将它们相交。如果您使用预测子集作为预限定符,该怎么办。预排序,但使用子集交集作为阈值条件。如果子集交集>n%,则完成交集,否则放弃