检查Haskell中常见整数的3个列表的最有效方法

时间:2013-07-05 21:50:07

标签: haskell

我有3个类型::[Integer]的列表,它们从最小到最大排序,所有任意长度和不同长度,在所有3中找到所有常见整数(如果有的话)的最有效方法是什么列表。

4 个答案:

答案 0 :(得分:8)

我不知道这是否是最快但应该非常快。使用列表或订购的事实。

repeats :: [Integer] -> [Integer] -> [Integer] -> [Integer]
repeats [] _ _    = []
repeats _ [] _    = []
repeats _ _  []   = []
repeats a@(x:xs) b@(y:ys) c@(z:zs)
   | x == y && y == z     = x : repeats xs ys zs
   | x <= y && x <= z     = repeats xs b c
   | y <= x && y <= z     = repeats a ys c
   | otherwise            = repeats a b zs

如果所有列表的第一个元素相同,那么我们将其添加到重复列表中。否则我们丢弃任何列表的最小值然后递归。如果您有n个列表,则可能需要二进制堆等。

修改

尾递归版

repeatsTail :: [Integer] -> [Integer] -> [Integer] -> [Integer]
repeatsTail f s t = go f s t []
   where go [] _ _  acc = reverse acc 
         go  _ [] _ acc = reverse acc 
         go  _ _ [] acc = reverse acc 
         go a@(x:xs) b@(y:ys) c@(z:zs) acc 
            | x == y && y == z     = go xs ys zs (x:acc)
            | x <= y && x <= z     = go xs b c acc 
            | y <= x && y <= z     = go a ys c acc 
            | otherwise            = go a b zs acc 

编辑2:

使用模式

答案 1 :(得分:7)

  • 最简洁的方式可能是使用函数Data.List.intersect:

    import Data.List (intersect)
    
    intersect [1, 2, 3] (intersect [1, 2] [2, 3])
    

    此解决方案的问题是intersect必须多次遍历列表才能找到匹配的元素。

  • 如果要避免这种开销,则必须至少暂时将元素存储在更有效的数据结构中。明显的,可能合理有效的解决方案是转换为集合并使用Data.Set.intersection:

    import Data.Set (fromList, toList, intersection)
    
    toList (intersection (fromList [1, 2, 3]) (intersection (fromList [1, 2]) (fromList [2, 3])))
    
  • 如果列表中的元素足够小以适合Int(而非Integer),则可以使用Data.IntSet代替Data.Set来< strong>提高绩效

    import Data.IntSet (fromList, toList, intersection)
    
    toList (intersection (fromList [1, 2, 3]) (intersection (fromList [1, 2]) (fromList [2, 3])))
    
  • 如果您需要更高的性能,则必须选择适合列表中数字的数据结构。也许bitsets适用于您的用例?或者您可以尝试以UArray Int Boolean函数使用accumArray

答案 2 :(得分:3)

对于简短列表,我只想使用elem构建一些东西。您可以利用这一见解,即所有三个列表中出现的任何数字都必须出现在最短列表中:所以您只需要考虑最短列表中的所有数字。

对于较长的列表,我会将列表转换为IntSet,然后使用intersection

import Data.IntSet

intersection3 :: [Int] -> [Int] -> [Int] -> [Int]
intersection3 a b c = toList $ fromAscList a `intersection` fromAscList b `intersection` fromAscList c

答案 3 :(得分:2)

这似乎也很快:

import Data.List (sort,group)

f a b c = map head
        . filter (not . null . drop 2) 
        . group
        . sort 
        $ a ++ b ++ c