我正在写一个mastermind求解器,在内循环中我计算两个列表的intersection with duplicates的长度。现在我的功能是
overlap :: Eq c => [c] -> [c] -> Int
overlap [] _ = 0
overlap (x:xs) ys
| x `elem` ys = 1 + overlap xs (delete x ys)
| otherwise = overlap xs ys
是否可以加快速度?如果有帮助,overlap
的参数是相同长度的短列表,最多6个元素,而c
类型的可能值少于10个。
答案 0 :(得分:2)
通常,(几乎)不可能提高此类算法的性能:为了删除两个无序和不可用列表中的重复项,可以在< EM>为O(n ^ 2)
通常,您可以通过以下条件(每种条件,不同的方法)提高性能:
如果您可以确保为每个列表创建/修改/ ...,则保持元素的顺序;这可能需要一些工程。在这种情况下,算法可以在O(n)中运行。
在这种情况下,您可以使用以下命令运行它:
--Use this only if xs and ys are sorted
overlap :: Ord c => [c] -> [c] -> Int
overlap (x:xs) (y:ys) | x < y = overlap xs (y:ys)
| x > y = overlap (x:xs) ys
| otherwise = 1 + overlap xs ys
overlap [] _ = 0
overlap _ [] = 0
通常,列表的排序可以在 O(n log n)中完成,因此比 O(n ^ 2)重叠算法更有效。新的重叠算法在 O(n)。
如果订购了c
,您也可以使用Data.Set
。在这种情况下,您可以使用在 O(n log n)中运行的fromList
方法为两个列表创建TreeSet,然后使用intersection
函数计算在 O(n)时间内交叉,最后使用size
函数计算大小。
--Use this only if c can be ordered
overlap :: Ord c => [c] -> [c] -> Int
overlap xs ys = size $ intersection (fromList xs) (fromList ys)
答案 1 :(得分:0)
您是否对多个ys
使用相同的xs
?
如果是,您可以尝试计算ys
中每个元素的哈希值并匹配此值,但请记住,计算哈希需要比6次比较更快。
如果其中任何一个是Ord
,您也可以提前对其进行排序,并仅验证ys
的必要部分。
但是,如果您需要快速随机访问列表不是最佳结构,您应该查看Data.Array
和Data.HashMap