题目描述
描述:大家都知道斐波那契数列,现在要求输入一个正整数 n ,请你输出斐波那契数列的第 n 项。斐波那契数列是一个满足 fib(x)={
1 x=1,2
fib(x−1)+fib(x−2) x>2
的数列。
数据范围:1≤n≤40。
要求:空间复杂度 O(1),时间复杂度 O(n) ,本题也有时间复杂度 O(logn) 的解法。
输入:4
返回值:3
说明:根据斐波那契数列的定义可知,fib(1)=1,fib(2)=1,fib(3)=fib(3-1)+fib(3-2)=2,fib(4)=fib(4-1)+fib(4-2)=3,所以答案为3。
输入:1
返回值:1
输入:2
返回值:1
解题思路
斐波那契数列:最直观的想法是,由于fib(x)=fib(x-1)+fib(x-2),其中x>=3,当x=1或者2时,fib(x)=1,那么我们不妨令a=1,b=1,c=1,其中循环从3开始直到n,不断交替变换,使得c=a+b,a=b,b=c,如此最后c即是我们想要的结果。
int Fibonacci(int n) {
int a=1,b=1,c=1;
for(int i=3;i<=n;i++)
{
c=a+b;
a=b;
b=c;
}
return c;
}
idea:由于题目直接给出了递推公式,那么我们也可以使用递归来做。
int Fibonacci(int n) {
int f;
if((n==1)||(n==2))
return 1;
if(n>=3)
f=Fibonacci(n-1)+Fibonacci(n-2);
return f;
}
idea:既然有递推公式,也可以使用递归来做,那么必然可以使用动态规划来做,因为递归是将大问题分解为小问题,而动态规划是将小问题推导为大问题。
int Fibonacci(int n) {
vector<int> dp(n);
dp[0]=1;
dp[1]=1;
for(int i=2;i<n;i++)
dp[i]=dp[i-1]+dp[i-2];
return dp[n-1];
}
数学:由于有fib(n)=fib(n-1)+fib(n-2),然后又有fib(n-1)=fib(n-2)+fib(n-3)……,该题本质上是求fib(n)对应计算了多少次的fib(1)和多少次的fib(0),那么我们可以转换为如下公式,最后结果为矩阵的n-1次方的第一行第一列的数。
typedef struct Matrix{
int a,b,c,d; //2*2矩阵
}Matrix;
Matrix Matrix_Multiply(Matrix &x,Matrix &y) //矩阵乘法
{
Matrix z;
z.a=x.a*y.a+x.b*y.c;
z.b=x.a*y.b+x.b*y.d;
z.c=x.c*y.a+x.d*y.c;
z.d=x.c*y.b+x.d*y.d;
return z;
}
Matrix Matrix_Quick_Pow(Matrix &x,int n) //矩阵快速幂
{
Matrix ans={1,0,0,1}; //初始化为单位矩阵
while(n>0)
{
if(n&1) //最低位为1
ans=Matrix_Multiply(ans, x); //将x乘入结果
x=Matrix_Multiply(x, x); //将x乘以x为下次做准备
n>>=1; //右移一位
}
return ans;
}
class Solution {
public:
int Fibonacci(int n) {
//最后结果为矩阵的n-1次方的第一行第一列的数
Matrix x={1,1,1,0}; //基础矩阵
Matrix ans=Matrix_Quick_Pow(x, n-1);
return ans.a;
}
};