tag: 入门动态规划
递推公式:
d
p
[
i
]
=
d
p
[
i
−
2
]
+
d
p
[
i
−
1
]
,
i
>
=
2
dp[i]=dp[i-2]+dp[i-1],i>=2
dp[i]=dp[i−2]+dp[i−1],i>=2
当i=0 i=1时单独处理
解法1:
使用dp数组,按照递推公式求解
class Solution {
int mod=(int)(1e9+7);
public int fib(int n) {
if(n==0){
return 0;
}
if(n==1){
return 1;
}
int[] dp=new int[n+1];
dp[0]=0;
dp[1]=1;
for(int i=2;i<=n;i++){
dp[i]=(dp[i-2]+dp[i-1])%mod;
}
return dp[n];
}
}
//O(n)
//O(n)
解法2:
由于没一个状态都只和前两个状态有关,因此可以用3个变量来交替,从而替代dp数组,减小空间开销
class Solution {
int mod=(int)(1e9+7);
public int fib(int n) {
if(n==0){
return 0;
}
if(n==1){
return 1;
}
int dp0,dp1,dp2=-1;
dp0=0;
dp1=1;
for(int i=2;i<=n;i++){
dp2=(dp0+dp1)%mod;
dp0=dp1;
dp1=dp2;
}
return dp2;
}
}
//O(n)
//O(1)
解法3:
解法一和解法二都是自底向上的动态规划解法,我们也可以使用自顶向下+备忘录的动态规划解法,使用递归形式完成
class Solution {
int mod=(int)(1e9+7);
int[]memo;
public int fib(int n) {
if(memo==null){
memo=new int[n+1];
}
if(n==0){
return 0;
}
if(n==1){
return 1;
}
if(memo[n]!=0){
return memo[n];
}else{
int ans=(fib(n-1)+fib(n-2))%mod;
memo[n]=ans;
return memo[n];
}
}
}
//O(n)
//O(n)
解法4:
快速幂
class Solution {
int mod=(int)(1e9+7);
public int fib(int n) {
if(n<=1){
return n;
}
long[][] mat={
{1,1},
{1,0}
};
long[][] ans={
{1},
{0}
};
int x=n-1;
//快速幂算法
while(x!=0){
if(x%2==1){
ans=multi(mat,ans);
}
mat=multi(mat,mat);
x/=2;
}
return (int)ans[0][0];
}
//矩阵相乘算法
public long[][] multi(long[][] a,long[][] b){
//a:p*q b: q*r
int p=a.length,q=a[0].length,r=b[0].length;
long[][] ans=new long[p][r];
for(int i=0;i<p;i++){
for(int j=0;j<r;j++){
for(int k=0;k<q;k++){
ans[i][j]+=a[i][k]*b[k][j];
ans[i][j]%=mod;
}
}
}
return ans;
}
}
//O(logn)
//O(1)