对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n-1)。第一个斐波拉契数为F(0) = 1。
给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007。
测试样例:
3
返回:2
对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n-1)。第一个斐波拉契数为F(0) = 1。
给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007。
3
返回:2
简洁、高效 的 递归解法,目前没有发现比我这个更简洁的代码了,50 ms,1238K
思路 :找规律,可用数学归纳法证明;
初始值:f(0) = 1, f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5...
f(10)
= f(9)+ f(8) = f(1)f(9)+f(0)f(8)
=2f(8)+ f(7) = f(2)f(8)+f(1)f(7)
=3f(7)+2f(6)= f(3)f(7)+f(2)f(6)
Map<Integer,Integer> mp = new HashMap<Integer, Integer>(); public int getNthNumber(int n) { if (n==1||n==0)return 1; if (n==2)return 2; if (mp.containsKey(n))return mp.get(n);//避免重复计算 long fn1=getNthNumber(n/2+1); // f(n+1) long fn_1=getNthNumber(n/2-1); // f(n-1) long fn=getNthNumber(n/2); // f(n) if (n%2==1) // F(2n+1) = F(n+1) F(n) + F(n) F(n-1), n>=1 mp.put(n,(int)((fn*fn1+fn*fn_1)%1000000007)); else // F(2n) = F(n) F(n) + F(n-1) F(n-1), n>=1 mp.put(n,(int)((fn*fn+fn_1*fn_1)%1000000007)); return mp.get(n); }
参考大佬的代码! class Fibonacci { public: void MultMetri(long long base1[2][2],long long base2[2][2]) { long long tmp[2][2]={0}; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) tmp[i][j]=(base1[i][0]*base2[0][j]+base1[i][1]*base2[1][j])%1000000007; } for(int i=0;i<2;i++) { for(int j=0;j<2;j++) base1[i][j]=tmp[i][j]; } } int getNthNumber(int n) { long long base[2][2]={{1,1},{1,0}}; long long ret[2][2]={{1,0},{1,0}}; while(n) { if(n%2) MultMetri(ret,base); MultMetri(base,base); n=n/2; } return (int)(ret[0][0]); } };
import java.util.*; public class Fibonacci { public int getNthNumber(int n) { // write code here long[][] base={{1,1},{1,0}}; long[][] ret={{1,0},{0,1}}; while(n!=0){ if(n%2==1) ret=MultMetri(ret,base); base=MultMetri(base,base); n=n>>1; } return (int)(ret[0][0]); } public static long[][] MultMetri(long[][] ret,long[][] base){ long[][] tmp=new long[2][2]; for(int i=0;i<2;i++) for(int j=0;j<2;j++) tmp[i][j]=(ret[i][0]*base[0][j]+ret[i][1]*base[1][j])%1000000007; for(int k=0;k<2;k++) for(int q=0;q<2;q++) ret[k][q]=tmp[k][q]; return ret; } }
来个python版本的,代码相当简洁 # -*- coding:utf-8 -*- class Fibonacci: def getNthNumber(self, n): res=base=[[1,1],[1,0]]#结果项和基底项 surplus=[[1,0],[0,1]]#surplus存储剩余项 while(n>1): if n&1: surplus=self.mutiply(surplus,res) res=self.mutiply(res,res) n=n>>1 res=self.mutiply(res, surplus) return res[0][0]%1000000007 def mutiply(self,a,b):#矩阵乘法 temp=[[0,0],[0,0]] for i in range(len(a)): for j in range(len(b)): for k in range(len(temp)): temp[i][j]+=a[i][k]*b[k][j]%1000000007 return temp
#include<bits/stdc++.h> typedef long long ll; class Fibonacci { public: int getNthNumber(int n) { // write code here if(mp.count(n)) return mp[n]; if(n==0) { mp[0]=1; return mp[0]; } if(n==1) { mp[1]=1; return mp[1]; } mp[n]=((ll)getNthNumber(n/2)*getNthNumber(n-n/2)%MOD +(ll)getNthNumber(n/2-1)*getNthNumber(n-n/2-1)%MOD)%MOD; return mp[n]; } private: unordered_map<int,int> mp; const int MOD=1000000007; };
class Fibonacci { public: void Mul(long long a[2][2], long long b[2][2]) { long long t[2][2] = {0}; for(int i=0;i<2;i++) for(int j=0;j<2;j++) t[i][j] = (a[i][0]*b[0][j] + a[i][1]*b[1][j])%(1000000007); for(int i=0;i<2;i++) for(int j=0;j<2;j++) a[i][j] = t[i][j]; } int getNthNumber(int n) { long long base[2][2] = {{1,1},{1,0}}; long long ret[2][2] = {{1,0},{1,0}}; while(n) { if(n&1) Mul(ret, base); Mul(base, base); n>>=1; } return ret[0][0]; } };
class Fibonacci { public: void multi(long long a[2][2], long long b[2][2]) { long long r[2][2]; r[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; r[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; r[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; r[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; a[0][0] = r[0][0] % 1000000007; a[0][1] = r[0][1] % 1000000007; a[1][0] = r[1][0] % 1000000007; a[1][1] = r[1][1] % 1000000007; } int getNthNumber(int n) { long long tmpA[2][2] = { { 1, 1 }, { 1, 0 } }; long long tmpB[2][2] = { { 1, 0 }, { 0, 1 } }; for (; n > 1; n = n / 2) { if (n & 1 == 1) { multi(tmpB,tmpA); } multi(tmpA, tmpA); } multi(tmpA, tmpB); return tmpA[0][0] ; } };
参考的程云老师的课程(第9次课)。
class Fibonacci {
public:
static const long long MOD =1000000007;
int getNthNumber(int n) {
// write code here
int a=1,b=1;
vector< vector<long long> > matrix(2);
vector< vector<long long> > res(2);
res[0].resize(2);
res[1].resize(2);
const int m[2][2]={{1,1},{1,0}};
for( int i=0; i<2; ++i )
for( int j=0; j<2; ++j )
matrix[i].push_back(m[i][j]);
res[0][0]=res[1][1]=1;
res[0][1]=res[1][0]=0;
while( n )
{
if( n&1 ) res=multiply(res,matrix);
matrix=multiply(matrix,matrix);
n >>= 1;
}
return (res[1][0]%MOD+res[1][1]%MOD)%MOD;
}
private:
vector< vector<long long> > multiply ( vector< vector<long long> >& a, vector< vector<long long> >& b )
{
vector< vector<long long> > temp(2);
for( int i=0; i<2; i++ )
temp[i].resize(2);
for( int i=0; i<2; i++ )
{
for( int j=0; j<2; j++ )
{
temp[i][j] = ((a[i][0]%MOD * b[0][j]%MOD )%MOD + (a[i][1]%MOD * b[1][j]%MOD )%MOD)%MOD;
}
}
return temp;
}
};
#define ll long long class Fibonacci { public: ll mod = 1e9+7; vector<vector<ll>> matrixPower(vector<vector<ll>>m,int p) { vector<vector<ll>>ret(2,vector<ll>(2,0)); for(int i=0;i<2;++i) ret[i][i] = 1; while(p) { if(p%2) { ret = multiMatrix(ret,m); } m = multiMatrix(m,m); p/=2; } return ret; } vector<vector<ll>> multiMatrix(vector<vector<ll>> m1,vector<vector<ll>> m2) { vector<vector<ll>>ans(2,vector<ll>(2,0)); for(int i=0;i<2;++i) for(int j=0;j<2;++j) { ans[i][j] = ((m1[i][0]%mod)*(m2[0][j]%mod) + (m1[i][1]%mod)*(m2[1][j]%mod))%mod; } return ans; } int getNthNumber(int n) { // write code here n+=1; if(n==1||n==2) return 1; long long m[2][2] = {{1,1},{1,0}}; vector<vector<ll>>base(2,vector<ll>(2,0)); for(int i=0;i<2;++i) for(int j=0;j<2;++j) base[i][j] = m[i][j]; vector<vector<ll>> res = matrixPower(base,n-2); return (res[0][0]+res[1][0])%mod; } };
import java.util.*; public class Fibonacci { public static final int mod = 1000000007; public int getNthNumber(int n ){ long[][] res = {{1, 1}, {1, 0}}; long[][] surplus = {{1,0},{0,1}}; while(n>1){ if(n % 2 == 1){ surplus = mutiply(surplus, res); } res = mutiply(res, res); n = n/2; } res = mutiply(res, surplus); return res[0][0] % 1000000007; } public int[][] mutiply(int[][] a, int[][] b) { long[][] temp = {{0,0},{0,0}}; for(int i = 0; i < 2; i++ ){ for(int j = 0; j < 2; j++){ for(int k = 0; k < 2; k++){ temp[i][j]+=a[i][k]*b[k][j]%1000000007; } } } return temp; } }