斐波那契数列多解
斐波那契数列在算法中占有很高的地位,
主要是很多题目背后的根源都是斐波那契数列
递归法
算法思路
递归
代码
1 | private fun fibonacci(n: Int): Int { |
复杂度分析
时间复杂度O(
时间复杂度怎么算呢?
首先这个斐波那契数列 递归求解 的数据结构是二叉树,并且一次只访问一个结点
怎么回事呢?
因为fibonacci
这个函数一次值返回一个数值,也就是每一次调用这个函数,就相当于访问一个节点,而 return
说明了这是二叉树,也就是两个分支
迭代法
算法思路
迭代,打表法
代码
1 | private fun fibonacci2(n: Int): Long { |
可以通过滚动数组节省空间
1 | private fun fibonacci2(n: Int): Long { |
复杂度分析
第一个时间复杂度是 O(n),空间复杂度是 O(n)
第一个时间复杂度是 O(n),空间复杂度是 O(1)
通项公式法
算法思路
首先我们看 斐波那契数列的递推公式:
我们假设两个常数 A、B 他们能组成下面形式,这是数学的惯用手法,递推公式求解通项公式的很多时候可以用这个方法,为的就是将递推公式变成等比数列的形式:
也就是这样的形式:
既然 A、B 可以有确定值,剩下的就是等比数列求解了:
这里我们用同样的方法,假设一个常数 C,然后等比数列求解:
最后代数进去,就是我们的通项公式了:
代码
然后我们就能可以使用通项公式来写这个函数了
1 | fun fibonacci3(n: Int): Double { |
复杂度分析
很多文章写这种方式时间复杂度为 O(1),这是明显错误的,因为计算 pow 的时间复杂度本就不是 O(1),总不能因为你调用了某个方法,就默认他方法的复杂度是 O(1) 吧
无论是官方的还是第三方的次幂运算(pow),最低也就能将复杂度降到O(logn)
而对于根号运算(sqrt),这个通常都是在操作系统底层,这种运算都是高度优化的,复杂度绝对不会高于 O(logn)
下面我展示一下我自己写的一个 pow 运算
1 | fun pow(x: Int, n: Int): Int { |
所以时间复杂度是 O(logn),空间复杂度是 O(1)
- Title: 斐波那契数列多解
- Author: lucas
- Created at : 2023-11-15 14:23:05
- Updated at : 2024-11-27 17:06:10
- Link: https://darkflamemasterdev.github.io/2023/11/15/斐波那契数列多解/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments