最小的自由数 - 分而治之的算法

时间:2015-07-16 06:01:33

标签: algorithm haskell divide-and-conquer

我正在读一本书功能算法设计珍珠。尝试实施最小自由数问题的分而治之解决方案。

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 中完成。

1 个答案:

答案 0 :(得分:3)

您有head . (\\) [0..]在O(N)时间内执行的病态输入。 \\定义为follows

(\\) =  foldl (flip delete)

delete x xs是O(N)操作,用于从x中删除第一个xsfoldl (flip delete) xs ys逐个从ys删除xs的所有元素。

[0..] \\ [0..9999999]中,我们总是在列表的头部找到要删除的下一个元素,因此可以在线性时间内评估结果。

如果您改为将minfree' (reverse [0..9999999])键入GHCi,则需要二次时间,并且您发现它几乎永远不会完成。

另一方面,分而治之算法不会减慢反向输入。