在问 · 算法题解

509. 斐波那契数

简单动态规划动态规划(滚动变量)力扣原题 ↗

题目描述

斐波那契数列的前两项是 F(0) = 0、F(1) = 1,从第 2 项起每一项等于它前面两项相加,即 F(n) = F(n - 1) + F(n - 2)。

输入整数 n,返回 F(n)。

示例 1
输入:n = 2
输出:1

解释:F(2) = 1 + 0 = 1。

示例 2
输入:n = 3
输出:2

解释:F(3) = 1 + 1 = 2。

示例 3
输入:n = 4
输出:3

解释:F(4) = 2 + 1 = 3。

数据范围

  • 0 <= n <= 30

解题思路:动态规划(滚动变量)

直接递归会把同一个 F(k) 重复算指数次。反过来从小到大递推:算 F(i) 只需要前两项,所以只用两个变量 a、b 分别保存 F(i-2) 和 F(i-1),每轮向前滚动一位。

为什么正确

第 i 轮结束时 a = F(i-1),b = F(i)。

复杂度分析

时间 O(n),空间 O(1)。

易错点

更新顺序要小心:先写 a = b 再写 b = a + b 会用到已被覆盖的 a。Python 用同时赋值 a, b = b, a + b,其他语言先存临时变量。n = 0 和 n = 1 要直接返回。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def fib(self, n: int) -> int:
        if n < 2:
            return n
        a, b = 0, 1
        for _ in range(2, n + 1):
            a, b = b, a + b
        return b

载入编辑器,自己跑一遍 →

其他解法

滚动变量的递推最简单,是线性时间;矩阵快速幂把线性递推转化为矩阵乘方,时间降到 O(log n)。

解法 2:矩阵快速幂 时间 O(log n),空间 O(1)

把递推写成矩阵形式:[[F(n+1), F(n)], [F(n), F(n−1)]] = [[1, 1], [1, 0]] 的 n 次方。用快速幂按 n 的二进制位累乘,只需 O(log n) 次 2×2 矩阵乘法,结果矩阵右上角就是 F(n)。

复杂度是对数级,适用于 n 极大且需要取模的场合,也能推广到任意线性递推。本题 n ≤ 30,优势体现不出来,代码也更长。

class Solution:
    def fib(self, n: int) -> int:
        # [[F(n+1), F(n)], [F(n), F(n-1)]] = [[1, 1], [1, 0]]^n
        def mul(a, b):
            return [[a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]],
                    [a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]]]

        res = [[1, 0], [0, 1]]
        base = [[1, 1], [1, 0]]
        while n:
            # 快速幂:按 n 的二进制位累乘
            if n & 1:
                res = mul(res, base)
            base = mul(base, base)
            n >>= 1
        return res[0][1]

动态规划 专题的其他题目

查看 动态规划 全部题目 →