我学习Haskell已经有4个月了,不得不说,学习曲线确实很陡峭(也很可怕:p)。
在解决了大约15个简单的问题后,今天我开始尝试我的第一个中等难度的HackerRank问题https://www.hackerrank.com/challenges/climbing-the-leaderboard/problem。
它有10个测试用例,我能够通过其中的6个,但其余的因超时而失败,现在有趣的部分是,我已经看到了一些潜在的性能提升点,例如,我正在使用
在解决了大约15个简单的问题后,今天我开始尝试我的第一个中等难度的HackerRank问题https://www.hackerrank.com/challenges/climbing-the-leaderboard/problem。
它有10个测试用例,我能够通过其中的6个,但其余的因超时而失败,现在有趣的部分是,我已经看到了一些潜在的性能提升点,例如,我正在使用
nub
从[Int]
中删除重复项,但仍然无法建立算法性能的心理模型,主要原因是不确定Haskell编译器会如何改变我的代码以及惰性在这里扮演的角色。import Data.List (nub)
getInputs :: [String] -> [String]
getInputs (_:r:_:p:[]) = [r, p]
findRating :: Int -> Int -> [Int] -> Int
findRating step _ [] = step
findRating step point (x:xs) = if point >= x then step else findRating (step + 1) point xs
solution :: [[Int]] -> [Int]
solution [rankings, points] = map (\p -> findRating 1 p duplicateRemovedRatings) points
where duplicateRemovedRatings = nub rankings
main :: IO ()
main = interact (unlines . map show . solution . map (map read . words) . getInputs . lines)
在GHCI中的测试用例
:l "solution"
let i = "7\n100 100 50 40 40 20 10\n4\n5 25 50 120"
solution i // "6\n4\n2\n1\n"
我有以下具体问题:
duplicateRemovedRankings
变量是只计算一次还是在每次 map 函数调用迭代中都计算。- 与命令式编程语言类似,我可以使用某种打印机制来验证上述问题,是否有相应的方法可以在 Haskell 中实现。
- 根据我的当前理解,这个算法的复杂度应该是,我知道
nub
是O(n^2)
findRating
是O(n)
getInputs
是O(1)
solution
是O(n^2)
如何推理和建立性能的心理模型。
如果这违反了社区准则,请评论并我会删除它。谢谢您的帮助 :)
Debug.Trace.trace
。 - David Eisenstatcontainers
包中的Data.IntSet
和Data.Map.Strict
,时间复杂度降至min(n * log n, m)
,其中n
是ranked
的长度,m
是player
的长度。 - user1984