以下策略應該非常有效。我已經在很多場合使用了這種變化來交叉遞增序列。
首先,我假設你有一些優先隊列可用(如果沒有,滾動自己的堆很容易)。快速鍵/值查找(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)
運行時間將是O(sum(sizes of sets) * log(number of sets) + count(times a point is in a pair of sets)
。特別要注意的是,如果兩組沒有交集,你就不會嘗試相交它們。
每套的內容基本上是隨機的嗎?如果不是這樣,也許你可以用最大的元素排列左邊的集合,用最小的順序排列集合,從而避免考慮很多空的交點。如果大多數集合都包含一堆附近的值,那麼這將工作得很好,而且如果大多數集合都包含最小和最大可能元素,那麼這將非常有效...... – 2011-04-27 11:34:13
呃......也許這個問題並不清楚;沒有「左」或「右」的一面,我只有一套集合。這些集合實際上是圖中頂點的最大集合,我正在尋找具有至少* k *個頂點的交集的集合對。 – 2011-04-27 12:03:21
比較兩組時,任意將其中一個稱爲「左」,另一個稱爲「右」。 – 2011-04-27 12:51:01