我正在读一本书功能算法设计珍珠。尝试实施最小自由数问题的分而治之解决方案。
minfree xs = minfrom 0 (length xs) xs
minfrom a 0 _ = a
minfrom a n xs = if m == b - a
then minfrom b (n-m) vs
else minfrom a (m) us
where b = a + 1 + (n `div` 2)
(us,vs) = partition (<b) xs
m = length us
但是这个工作并不比人们可能称之为“天真”的解决方案更快。解。这是
import Data.List ((\\))
minfree' = head . (\\) [0..]
我不知道为什么会这样,分而治之的算法有什么不对,以及如何改进它。
尝试使用BangPatterns
,实现partition
的版本,该版本也返回元组中第一个列表的长度,因此它消除了m =length us
的额外遍历。他们都没有改善。
第一个需要5秒以上,而第二个几乎立即在输入[0..9999999]
的 ghci 中完成。
答案 0 :(得分:3)
您有head . (\\) [0..]
在O(N)时间内执行的病态输入。 \\
定义为follows:
(\\) = foldl (flip delete)
delete x xs
是O(N)操作,用于从x
中删除第一个xs
。 foldl (flip delete) xs ys
逐个从ys
删除xs
的所有元素。
在[0..] \\ [0..9999999]
中,我们总是在列表的头部找到要删除的下一个元素,因此可以在线性时间内评估结果。
如果您改为将minfree' (reverse [0..9999999])
键入GHCi,则需要二次时间,并且您发现它几乎永远不会完成。