当前位置:   article > 正文

LeetCode 509:斐波那契数

leetcode 509

题意:

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给定 n ,请计算 F(n)

示例:

示例1:

**输入:**n = 2
**输出:**1
**解释:**F(2) = F(1) + F(0) = 1 + 0 = 1

示例2:

**输入:**n = 3
**输出:**2
**解释:**F(3) = F(2) + F(1) = 1 + 1 = 2

示例3:

**输入:**n = 4
**输出:**3
**解释:**F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

  • 0 <= n <= 30

我的解法:

思路:

1.创建一个fn_list列表,用于保存从f0,f1,…,fn,并将f0 = 0, f1 = 1存入列表。

  1. 如果n≤1,返回 fn_list的第n项;
如果n>1,根据公式F(n) = F(n - 1) + F(n - 2),依次求出f2,…,fn-1,并存入fn_list。返回fn_list[n-1] + fn_list[n-2]。
class Solution:
    def fib(self, n: int) -> int:
        fn_list = [0,1]
        #判断n是否大于1
        if n <= 1:
            return fn_list[n]
        #当n大于1时
        i = 2
        while i < n:
            f = fn_list[i-1] + fn_list[i-2] 
            fn_list.append(f)
            i += 1
        return fn_list[n-1] + fn_list[n-2]

分析:

  • 时间复杂度:O(n)。
  • 空间复杂度:O(n)。
提交结果执行时间内存消耗
通过40 ms14.8 MB

2.注意:不要漏掉n≤1的情况。

官方解法

### 方法一:动态规划**滑动窗口**

#### 思路:

斐波那契数的边界条件是 F(0)=0 和 F(1)=1。当 n>1时,每一项的和都等于前两项的和,因此有如下递推关系:

F(n)=F(n-1)+F(n-2)

由于斐波那契数存在递推关系,因此可以使用动态规划求解。动态规划的状态转移方程即为上述递推关系,边界条件为 F(0) 和 F(1)。

根据状态转移方程和边界条件,可以得到时间复杂度和空间复杂度都是 O(n) 的实现。由于 F(n) 只和 F(n-1)与 F(n-2) 有关,因此可以使用「滚动数组思想」把空间复杂度优化成 O(1)。如下的代码中给出的就是这种实现。
class Solution:
    def fib(self, n: int) -> int:
        if n < 2:
            return n
        
        p, q, r = 0, 0, 1
        for i in range(2, n + 1):
            p, q = q, r
            r = p + q
        
        return r

#### 复杂度分析

- 时间复杂度:O(n)。
- 空间复杂度:O(1)。

执行用时:40 ms;内存消耗:14.8 MB。

### 方法二:矩阵快速幂

方法一的时间复杂度是 O(n)。使用矩阵快速幂的方法可以降低时间复杂度。

首先我们可以构建这样一个递推关系:

[ 1 1 1 0 ] [ F ( n ) F ( n − 1 ) ] = [ F ( n ) + F ( n − 1 ) F ( n ) ] = [ F ( n + 1 ) F ( n ) ] \left[

1110
\right]\left[
F(n)F(n1)
\right]=\left[
F(n)+F(n1)F(n)
\right]=\left[
F(n+1)F(n)
\right] [1110][F(n)F(n1)]=[F(n)+F(n1)F(n)]=[F(n+1)F(n)]

因此:

[ F ( n + 1 ) F ( n ) ] = [ 1 1 1 0 ] n [ F ( 1 ) F ( 0 ) ] \left[

F(n+1)F(n)
\right]=\left[
1110
\right]^{n}\left[
F(1)F(0)
\right] [F(n+1)F(n)]=[1110]n[F(1)F(0)]

令:

M = [ 1 1 1 0 ] M=\left[

1110
\right] M=[1110]

因此只要我们能快速计算矩阵 M 的 n 次幂,就可以得到 F(n) 的值。如果直接求取 M^n,时间复杂度是 O(n),可以定义矩阵乘法,然后用快速幂算法来加速这里 M^n的求取。
class Solution:
    def fib(self, n: int) -> int:
        if n < 2:
            return n
        
        q = [[1, 1], [1, 0]]
        res = self.matrix_pow(q, n - 1)
        return res[0][0]
    
    def matrix_pow(self, a: List[List[int]], n: int) -> List[List[int]]:
        ret = [[1, 0], [0, 1]]
        while n > 0:
            if n & 1:
                ret = self.matrix_multiply(ret, a)
            n >>= 1
            a = self.matrix_multiply(a, a)
        return ret

    def matrix_multiply(self, a: List[List[int]], b: List[List[int]]) -> List[List[int]]:
        c = [[0, 0], [0, 0]]
        for i in range(2):
            for j in range(2):
                c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j]
        return c

#### 复杂度分析:

- 时间复杂度:O(logn)。
- 空间复杂度:O(1)。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/1021292
推荐阅读
相关标签
  

闽ICP备14008679号