简体   繁体   English

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

[英]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删除的所有元素ysxs一个接一个。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM