簡體   English   中英

以最優化方式求兩組交集

[英]Intersection of two sets in most optimized way

給定兩組值,我必須找出它們之間是否有任何共同元素,即它們的交集是否為空。

哪個標准 C# 集合最適合(在性能方面)用於此目的? 我知道linq有一個Intersect擴展方法來找出兩個列表/數組的交集,但我的重點是在Big-O notation方面的性能。

如果我還必須找出兩個集合的交集怎么辦?

好吧,如果您使用 LINQ 的Intersect方法,它將構建第二個序列的HashSet ,然后對照它檢查第一個序列的每個元素。 所以它是 O(M+N)... 你可以使用foo.Intersect(bar).Any()來提前退出。

當然,如果您首先將一個(任一)集合存儲在HashSet<T>中,您可以迭代另一個集合,檢查每個步驟的包含情況。 盡管如此,您仍然需要構建該集合。

從根本上說,無論您做什么,您都會遇到 O(M+N) 問題-不會比這更便宜(您總是有可能必須查看每個元素)並且您的哈希碼是否合理,您應該能夠輕松實現這種復雜性。 當然,某些解決方案可能會提供比其他解決方案更好的常數因子……但這是性能而不是復雜性;)

編輯:如評論中所述,還有ISet<T>.Overlaps - 如果您已經設置了靜態類型的ISet<T>或具體實現,則調用Overlaps可以更清楚地了解您在做什么。 如果您的兩個集合都是靜態類型為ISet<T> ,請使用larger.Overlaps(smaller) (其中更大和更小是根據集合的大小),因為我希望Overlaps的實現來迭代參數並根據您調用它的集合的內容檢查每個元素。

如前所述,應用Any()會給你一些性能。

我在相當大的數據集上對其進行了測試,結果提高了 25%。

同樣應用larger.Intersect(smaller)而不是相反的方法非常重要,在我的情況下,它提供了 35% 的改進。

在應用 intersect 之前對列表進行排序又得到了 7-8%。

要記住的另一件事是,根據用例,您可以完全避免應用相交。

例如,對於整數列表,如果最大值和最小值不在同一個邊界內,則您不需要應用相交,因為它們永遠不會這樣做。

對於第一個字母具有相同思想的字符串列表也是如此。

再次根據您的情況,盡可能多地嘗試找到無法避免調用它的交集規則。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM