列表性能的长度为n的子序列

Vik*_*ren 4 performance haskell

我实现了这个答案的一个版本/sf/answers/694429781/(我不知道回答的人的意图是什么)

sublistofsize 0 _        = [[]]
sublistofsize _ []       = []
sublistofsize n (x : xs) = sublistsThatStartWithX ++ sublistsThatDontStartWithX
  where sublistsThatStartWithX = map (x:) $ sublistofsize (n-1) xs
        sublistsThatDontStartWithX = sublistofsize n xs
Run Code Online (Sandbox Code Playgroud)

我不确定的是什么 sublistsThatStartWithX = map (x:) $ sublistofsize (n-1) xs

我假设map(x :)在性能方面提出了问题,但不确定如何解决它.我做过剖析print $ length $ sublistofsize 5 $ primesToTakeFrom 50

COST CENTRE                                  MODULE                                        no.     entries  %time %alloc   %time %alloc
sublistofsize                             Main                                          112     4739871   46.9   39.9    96.9  100.0
 sublistofsize.sublistsThatDontStartWithX Main                                          124     2369935    2.2    0.0     2.2    0.0
 sublistofsize.sublistsThatStartWithX     Main                                          116     2369935   47.8   60.1    47.8   60.1
Run Code Online (Sandbox Code Playgroud)

我是否以良好的方式实施了它?有没有更快的方法呢?

Ber*_*rgi 14

我假设map(x :)给出了一个明智的问题

编号map有效编码并以线性时间运行,此处没有问题.

但是,您的递归可能是一个问题.你们都调用sublistofsize (n-1) xssublistofsize n xs,这-发出启动列表sublistofsize m (_:_:ys)-不评价长期sublistofsize (m-1) ys的两倍,因为在不同的递归步骤,它们之间没有共享.

所以我应用动态编程来获取

subsequencesOfSize :: Int -> [a] -> [[a]]
subsequencesOfSize n xs = let l = length xs
                          in if n>l then [] else subsequencesBySize xs !! (l-n)
 where
   subsequencesBySize [] = [[[]]]
   subsequencesBySize (x:xs) = let next = subsequencesBySize xs
                             in zipWith (++) ([]:next) (map (map (x:)) next ++ [[]])
Run Code Online (Sandbox Code Playgroud)

不是附加空列表是最美丽的解决方案,但你可以看到我如何使用zipWith移位列表,以便结果next使用两次 - 一次直接在长度为n的子序列列表中,一次在子序列列表中长度为n + 1.

在GHCI中进行测试:set +s,您可以看到这比天真的解决方案更快:

*Main> length $ subsequencesOfSize 7 [1..25]
480700
(0.25 secs, 74132648 bytes)
(0.28 secs, 73524928 bytes)
(0.30 secs, 73529004 bytes)
*Main> length $ sublistofsize 7 [1..25] -- @Vixen (question)
480700
(3.03 secs, 470779436 bytes)
(3.35 secs, 470602932 bytes)
(3.14 secs, 470747656 bytes)
*Main> length $ sublistofsize' 7 [1..25] -- @Ganesh
480700
(2.00 secs, 193610388 bytes)
(2.00 secs, 193681472 bytes)
*Main> length $ subseq 7 [1..25] -- @user5402
480700
(3.07 secs, 485941092 bytes)
(3.07 secs, 486279608 bytes)
Run Code Online (Sandbox Code Playgroud)