[英]The smallest free number - divide and conquer algorithm
I'm reading a book Pearls of Functional Algorithm Design . 我正在读一本书“功能算法设计珍珠” 。 Tried implementing the divide and conquer solution for smallest free number problem.
尝试实施最小的自由数问题的分而治之解决方案。
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
But this one works no faster than the solution that one might call "naive" solution. 但是这个工作并不比人们称之为“天真”解决方案的解决方案更快。 Which is
这是
import Data.List ((\\))
minfree' = head . (\\) [0..]
I don't know why this is like this, what's wrong with the divide and conquer algorithm and how to improve it. 我不知道为什么会这样,分而治之算法有什么问题以及如何改进它。
Tried using BangPatterns
, implementing the version of partition
that also returns first list's length in the tuple, so it eliminates additional traversal for m =length us
. 尝试使用
BangPatterns
,实现也在元组中返回第一个列表长度的partition
版本,因此它消除了m =length us
额外遍历。 None of them made improvement. 他们都没有改善。
First one takes more than 5 seconds, whereas second one does it almost instantly in ghci on input [0..9999999]
. 第一个需要超过5秒,而第二个几乎立即在输入
[0..9999999]
ghci中 。
You have pathological input on which head . (\\\\) [0..]
你有
head . (\\\\) [0..]
病理输入head . (\\\\) [0..]
head . (\\\\) [0..]
performs in O(N) time. head . (\\\\) [0..]
在O(N)时间内执行。 \\\\
is defined as follows : \\\\
定义如下 :
(\\) = foldl (flip delete)
delete x xs
is an O(N) operation that removes the first x
from xs
. delete x xs
是一个O(N)操作,它从xs
中删除第一个x
。 foldl (flip delete) xs ys
deletes all elements of ys
from xs
one by one. foldl (flip delete) xs ys
删除的所有元素ys
从xs
一个接一个。
In [0..] \\\\ [0..9999999]
, we always find the next element to be deleted at the head of the list, so the result can be evaluated in linear time. 在
[0..] \\\\ [0..9999999]
,我们总是在列表的头部找到要删除的下一个元素,因此可以在线性时间内评估结果。
If you instead type minfree' (reverse [0..9999999])
into GHCi, that takes quadratic time and you find that it pretty much never finishes. 如果您改为将
minfree' (reverse [0..9999999])
键入GHCi,则需要二次时间,并且您发现它几乎从未完成。
The divide-and-conquer algorithm on the other hand would not slow down on the reversed input. 另一方面,分而治之算法不会减慢反向输入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.