您在評論中提到,您的套件將全部爲座標對(Int,Int)
,其中每個座標的範圍爲[1..10]
。
在這種情況下,您應該使用「位集」,以便您可以使用處理器的按位AND和OR操作來設置交集和聯合。
模塊Data.BitSet.Dynamic可以用於這一目的:
import qualified Data.BitSet.Dynamic as B
type Bset = B.BitSet B.FasterInteger
-- convert a list of points into a bit set
toSet :: [(Int,Int)] -> Bset
toSet points = B.fromList [ fromIntegral (r*10+c) | (r,c) <- points ]
-- do two bit sets have common elements?
commonElements :: Bset -> Bset -> Bool
commonElements a b = not $ B.null $ B.intersection a b
-- add a point to a bit set
addPoint :: Bset -> (Int,Int) -> Bset
addPoint a (r,c) = B.insert (fromIntegral $ r*10+c) a
-- convert a bit set to a list of points
toPoints :: Bset -> [(Int,Int)]
toPoints a = [ (q,r) | x <- B.toList a, let (q,r) = divMod (fromIntegral x) 10 ]
-- does a set have a point?
hasPoint :: Bset -> (Int,Int) -> Bool
hasPoint a (r,c) = B.member (fromIntegral $ r*10+c) a
檢測是否兩套有任何共同的元件或點是否在一組是非常快的。
我認爲找出最好的方法就是嘗試它(測量它) - 這只是我的直覺,但我認爲*列表<100您可能會更快通過使用列表(可能首先排序) – Carsten
「爲了記錄,我將不得不檢查大量相當小的列表(大小小於100的〜10^5)「 - 您是否要針對單個列表檢查所有列表,還是需要測試所有列表可能的配對? – duplode
注意:你**不能**使用Set並獲得一個嚴格等價的函數。使用'Set's意味着有'Ord a'約束,而你的函數只有'Eq a'。如果你允許'Ord a',一個等效的方法可以是對這兩個列表進行排序,然後使用類似'group'的東西,然後比較「線性」(不需要使用elem來檢查頭部)。事實上,我相信這個問題*如果只允許'Eq a'需要* O(n^2)... – Bakuriu