递归计算斐波那契数列:
class Solution: def Fibonacci(self , n ): if n <= 2: return 1 else: return self.Fibonacci(n-1)+self.Fibonacci(n-2)
当计算斐波那契数列时,使用递归的方式是比较简洁的,但是效率不高,尤其是当计算较大的斐波那契数时,递归会导致重复计算,造成性能下降。可能出现运行超时现象。
- 时间复杂度:O(2^n)。递归版本的斐波那契数列实现会重复计算许多相同的子问题,导致指数级别的时间复杂度。
- 空间复杂度:O(n)。递归版本需要消耗系统栈空间,递归深度达到 n,因此空间复杂度随着输入规模线性增长。
更高效的方法是使用迭代或动态规划。
迭代版本:
#coding:utf-8 # # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # # @param n int整型 # @return int整型 # class Solution: def Fibonacci(self , n ): if n < 2: return n else: fa = 0 #f0=0 fb = 1 #f1=1 for i in range(2,n+1): fa,fb = fb, fa+fb return fb
在这个改进版本中,我们使用两个变量 fa
和 fb
来迭代计算斐波那契数列。初始时,fa
表示第 0 项,fb
表示第 1 项。然后,循环从第 2 项开始,利用迭代更新 fa
和 fb
的值,直到计算到第 n
项。
这种迭代的方式避免了递归带来的重复计算,因此在效率上更高。
- 时间复杂度:O(n)。迭代版本使用循环从第 2 项开始计算斐波那契数值,总共需要进行 n-1 次迭代。
- 空间复杂度:O(1)。迭代版本只使用了常数级别的额外空间,无论输入规模是多少,所需的额外空间都保持不变。
使用动态规划的版本可以进一步优化斐波那契数列的计算效率。动态规划将问题划分为子问题,并利用子问题的解构建更大规模问题的解。
动态规划版本:
class Solution: def Fibonacci(self , n ): #首先处理边界情况 if n < 2: return n #用于存储计算过程中的斐波那契数值 f = [0]* (n+1) #初始值 f[0] = 0 f[1] = 1 #递推计算斐波那契数列 for i in range(2,n+1): f[i] = f[i-1] + f[i-2] return f[n]
我们使用一个数组 f
来存储计算过程中的斐波那契数值。初始时,我们将数组中的前两个元素设置为 0 和 1,分别代表第 0 项和第 1 项。
然后,我们通过一个循环从第 2 项开始,使用递推关系f[i] = f[i - 1] + f[i - 2]
计算每一项的斐波那契数值。最终,f[n]
即为第 n
项的斐波那契数值。
注意: f= [0] * (n + 1)
是一个将列表 f 初始化为长度为 n+1
的列表,并且列表中的每个元素都初始化为 0 的操作。
在斐波那契数列的动态规划解法中,我们使用列表 f
来存储计算过程中的斐波那契数值。由于斐波那契数列的索引是从 0 开始的,因此我们需要初始化列表 f
的长度为 n+1
,这样可以确保列表中的索引从 0 到 n 都有对应的位置。
这里使用乘法的方式,将 0 乘以 (n + 1)
来创建一个含有 n+1
个元素的列表,并将每个元素初始化为 0。例如,当 n
的值为 5 时,f
列表的初始化结果为 [0, 0, 0, 0, 0, 0]
。
- 时间复杂度:O(n)。动态规划版本利用了子问题之间的重叠性质,通过迭代计算并存储中间结果,总共需要进行 n-1 次迭代。
- 空间复杂度:O(n)。动态规划版本使用了一个长度为 n+1 的列表
f
来存储斐波那契数值,占用了线性额外空间。