我正在Haskell学习。

我一直在实现一个列出除数的函数。
我的第一个代码在这里:

码:

divisors :: Integral a => a -> [a]
divisors n
  | n < 1 = []
  | otherwise = filter ((== 0) . (mod n)) [1..n]


此代码与Making a list of divisors in Haskell几乎相同。
它有效但是很慢。

我觉得除以每个[1..n]效率不高。
是否有另一种聪明的方法来列出除数列表?

更新:

对于n < 1[1..n][]相同。
因此,根本不需要警卫:

divisors :: Integral a => a -> [a]
divisors n = filter ((== 0) . (mod n)) [1..n]

最佳答案

强制性单子代码:

import Control.Monad

divisors = map product . mapM (scanl (*) 1) . group . factors


factors与您其他链接的问题相同。

您已经在使用List monad中的sequence,无需显式调用concatMapmapM f等效于sequence . map f)。

不过,该列表不会被排序,就像您最初按顺序划分的O(n)代码生成的列表一样,您可以通过简单的技巧将其设置为O(sqrt(n)),尽管它仍然可以平均而言,它比此代码要慢得多。

08-26 15:10