聊聊斐波那契数列中递归的重复计算
聊聊斐波那契数列中递归的重复计算#
所谓的斐波纳契数列是指:
前2个数是 0 和 1 。
第 i 个数是第 i-1 个数和第i-2 个数的和。
斐波纳契数列的前10个数字是:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...
1 递归实现#
根据定义,很快就能写出递归实现:
public int fibonacci(int n) { if (n < 2) {return 0;} if (2 == n) {return 1;} return fibonacci(n - 1) + fibonacci(n - 2); }
但是,这个函数去执行的时候,会发现非常的慢。那是什么原因呢?
我们仔细观察一下,每一次递归的时候,我们都会调用两个,所以,计算时,从n、n-1、… 0会是一个金字塔,二叉树的分布,也就是靠近0的底层,会有2^n次运算,就是一个指数级运算,计算时间复杂度为O(2^n),运算速度是非常慢的。
原因是什么呢?假如,我们计算的是10,那么它相应的要计算 9 + 8,而9要计算 8 + 7, 8又要计算 7 + 6.相当于越往底层去,计算的次数越多。
10 / \ 9 8 / \ / \ 8 7 7 6 ...
2 递归改进#
那么避免重复计算的方法就是,每计算得到一个值,便用一个数组保存这个值,下次计算该值的时候直接引用就可以了。
public int fibonacci(int n) { int[] array = new int[n + 1]; if (n < 2) {return 0;} if (2 == n) {return 1;} array[1] = 0; array[2] = 1; return helper(array, n); } private int helper(int[] array, int n) { if (n < 2) { return 0; } if (2 == n) { return 1; } array[n] = helper(array, n - 1) + array[n - 2]; // 保存每次计算的结果 return array[n]; }
但这种方法不是尾递归的,所以,调用栈内存会比较多。
3 迭代法#
用迭代法来计算是最简单,速度也最快的。
public int fibonacci(int n) { int[] array = new int[n + 1]; if (n < 2) {return 0;} if (2 == n) {return 1;} array[1] = 0; array[2] = 1; for (int i = 3; i <= n; i++) { array[i] = array[i - 1] + array[i - 2]; } return array[n]; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端