兩個有序集合求交集

2021-10-07 10:55:41 字數 1823 閱讀 7555

方案一:暴力法,for*for,時間複雜度o(n*n)

當資料量很大時,不可取

方案二:拉鍊法

有序集合1

有序集合2

兩個指標指向首元素,比較元素的大小:

(1)如果相同,放入結果集,隨意移動乙個指標;

(2)否則,移動值較小的乙個指標,直到隊尾;

這種方法的好處是:

(1)集合中的元素最多被比較一次,時間複雜度為o(n);

(2)多個有序集合可以同時進行

方案三:分桶並行優化

資料量大時,url_id分桶水平切分+並行運算是一種常見的優化方法,如果能將list1和list2分成若干個桶區間,每個區間利用多執行緒並行求交集,各個執行緒結果集的並集,作為最終的結果集,能夠大大的減少執行時間。

舉例:有序集合1

有序集合2

求交集,先進行分桶拆分:

桶1的範圍為[1, 9]

桶2的範圍為[10, 100]

桶3的範圍為[101, max_int]

於是:集合1就拆分成

集合a集合b

集合c{}

集合2就拆分成

集合d集合e

集合e{}

每個桶內的資料量大大降低了,並且每個桶內沒有重複元素,可以利用多執行緒平行計算:

桶1內的集合a和集合d的交集是x

桶2內的集合b和集合e的交集是y

桶3內的集合c和集合d的交集是z{}

最終,集合1和集合2的交集,是x與y與z的並集,即集合。

方案四:bitmap再次優化

資料進行了水平分桶拆分之後,每個桶內的資料一定處於乙個範圍之內,如果集合符合這個特點,就可以使用bitmap來表示集合:

如上圖,假設set1和set2的所有元素都在桶值[1, 16]的範圍之內,可以用16個bit來描述這兩個集合,原集合中的元素x,在這個16bitmap中的第x個bit為1,此時兩個bitmap求交集,只需要將兩個bitmap進行「與」操作,結果集bitmap的3,5,7位是1,表明原集合的交集為。

水平分桶,bitmap優化之後,能極大提高求交集的效率,但時間複雜度仍舊是o(n)。bitmap需要大量連續空間,占用記憶體較大。

方案五:跳表skiplist

有序鍊錶集合求交集,跳表是最常用的資料結構,它可以將有序集合求交集的複雜度由o(n)降至接近o(log(n))。

集合1集合2

要求交集,如果用拉鍊法,會發現1,2,3,4,20,21,22,23都要被無效遍歷一次,每個元素都要被比對,時間複雜度為o(n),能不能每次比對「跳過一些元素」呢?

跳表就出現了:

集合1建立跳表時,一級只有三個元素,二級與普通鍊錶相同。

集合2由於元素較少,只建立了一級普通鍊錶。

如此這般,在實施「拉鍊」求交集的過程中,set1的指標能夠由1跳到20再跳到50,中間能夠跳過很多元素,無需進行一一比對,跳表求交集的時間複雜度近似o(log(n))。

Python演算法 如何求兩個有序集合的交集

兩個有序集合,集合中每個元素都是一段範圍,求其交集。例如集合和的交集為。最簡單方法就是遍歷兩個集合,針對集合中每個元素判斷是否有交集,如果有,則求其交集。方法一沒有利用集合有序的特點,因此,不是最佳的方法。假設兩個集合s1,s2,當前比較集合為s1 i 與s2 j 其中i與j分別是集合s1與s2的下...

求兩個有序整型陣列的交集

有兩個有序的整型陣列a和b 沒有重複元素 他們的長度分別為lena和lenb,求出他們的共同元素。例如 a 0,1,3,5,7,9,11 b 2,3,4,7,11 它們的交集為。求交集的方法有很多種,但陣列的長度會影響演算法的效率。2.1.1 二路歸併 對於陣列a,b分別以i,j從頭遍歷陣列。如果當...

兩個整數集合最快演算法求交集

b 兩個整數集合,設計乙個演算法求他們的交集,盡可能的高效。一 第一種演算法,暴力求解,直接採用遍歷或者列舉的方法,這種辦法最簡單易想,但是時間複雜度比較高,為 o n 2 這是最複雜的情況。二 預處理。其實思想和c語言中的預處理一樣,對資料記性歸一化處理。說白了,就是對陣列先進行排序。陣列排序的演...