斐波那契作为动态规划入门题,大家肯定都会写,毕竟题目都把递推公式给出了,直接一个循环就结束了。
贴下题目链接:LCR 126. 斐波那契数
但是直接使用循环,时间复杂度是 O(N) 的,在数据量很大的情况下,也是会超时的。那能不能用 O(logN) 的做法来完成呢?可以!具体怎么做,接着看吧。
对于数列递推问题,可以使用矩阵快速幂进行加速。
矩阵快速幂用于求解一般性问题:给定大小为
n*n
的矩阵 M,求答案矩阵 Mk,并对答案矩阵中每个元素对 MOD 取模。
对于本题而言,某个 f(n)
是从 f(n-1)
和
f(n-2)
推导而来的,即
f(n) = f(n-1) + f(n-2)
,可以将其依赖的状态存成列向量:\(\begin{bmatrix} f(n-1) \\ f(n-2)
\end{bmatrix}\)
那么目标值 f(n)
所在的矩阵为:\(\begin{bmatrix} f(n) \\ f(n-1)
\end{bmatrix}\)
根据矩阵乘法可以得出:\(\begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} \ast \begin{bmatrix} f(n-1) \\ f(n-2) \end{bmatrix}\)
于是乎,可以令 \(mat = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\)
初始状态下,存在矩阵 \(\begin{bmatrix} f(1) \\ f(0) \end{bmatrix}\),根据斐波那契递推式可以得出:
\(\begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix} = \underbrace{ mat \ast mat \ast \cdots \ast mat }_{n-1} \ast \begin{bmatrix} f(1) \\ f(0) \end{bmatrix}\)
由于矩阵乘法具有「结合律」,最终可以得出:
\(\begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix} = mat^{n-1} \ast \begin{bmatrix} f(1) \\ f(0) \end{bmatrix}\)
由此,我们只需要计算 \(mat^{n-1}\) 就可以求解出最终答案,这个过程可以使用矩阵快速幂来解决。
class Solution { |
- 时间复杂度:O(logN)
- 空间复杂度:O(1)
PS: 如果不想在乎传入
mul()
方法的参数顺序,可以将ans
初始化成:
long[][] ans = new long[][] {
{1, 0}, // f(1)
{0, 0} // f(0)
};结果保持不变。
类似题目:1137. 第 N 个泰波那契数
class Solution { |