haskell - Haskell 动态程序效率
问题描述
我正在学习更多关于动态编程的知识,并试图在 haskell 中实现它。我正在用不同的方法编写算法进行测试,发现一种比另一种更快。这是斐波那契问题
fib1 :: [Integer]
fib1 = 0:1:zipWith (+) fib1 (tail fib1)
fib2 :: [Integer]
fib2 = 0:1:[(fib2 !! (n-1)) + (fib2 !! (n-2)) | n <- [2..]]
fib1 比 fib2 快得多,但我不知道为什么。fib2 看起来很直观,第 n 个数字是 (n-1)st 加上 (n-2)nd。我得到了 fib1,但看起来它每次都在压缩整个列表,所以不会花费更长的时间。只是计算下一个索引?
解决方案
@netom 抱歉,但我认为这不是正在发生的事情。我按时进行了一些测试,计算出第 10000 个数字需要 0.7 秒。在同一次运行中,可以立即计算出第 10000 + 9999(第 10001 个数字),表明它被记住了。
然后,我测试了新计算第 10001 个所需的时间,计算第 10001 个所需的时间与计算第 10000 个并记住所有其余部分的时间相同。要计算第 10001 个,它不会计算 10000 和 9999(在单独的递归中),它的行为就像你期望的那样,如果它只是索引了记住的列表。
然而,递归函数需要几乎两倍的时间!所以他们都正确地使用了动态编程。但正如我发现的那样,fib2 每一步都需要 O(n) 来访问数组,但 fib1 每一步都需要 O(1) 压缩它。
推荐阅读
- python - 我怎样才能在电视节目中获得实体?(连接电话)
- apache-flink - 为什么在作业提交到 Yarn 后运行 Flink 批处理程序会立即退出?
- mariadb - 收到 10.1.48-MariaDB-0ubuntu0.18.04.1 的 CTE 语法错误
- python - 将 pandas 数据框列合并为 1 列并忽略 NaN
- go - 无法将 res.Data(类型 []twitterstream.rulesResponseValue)转换为类型 []byte
- optimization - .Net 5 是否有后备列表实现?
- post - 在这种情况下如何获取从“POST”发送的数据?
- spring-batch - 如何在 Spring Batch - 不同名称中处理这个用例?
- python - 如何获取传递给函数内函数的对象的名称?
- c# - C# - .NET 4.7 - 流编码问题 - 不正确读取 unicode 和 ascii 字符