斐波那契数列
题目描述
写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。
斐波那契数列的定义:F(0) = 0, F(1) = 1;F(N) = F(N - 1) + F(N - 2), 其中 N > 1
解析
- 解法一:递归
第一想法必是递归求解,代码如下,然而由代码可以看出该方法存在着大量的重复计算。当计算fib(n-1)时,会需要计算fib(n-2)和fib(n-3),而在递归完fib(n-1)后,又需要递归计算fib(n-2),而无法利用前者已计算过的值(因为并不会在内存中)。由此缺点出发,想出解法二。
public int fib(int n) {
if(n==0) return 0;
if(n==1) return 1;
int num = (fib(n-1)+fib(n-2))%1000000007;
return num;
}
- 解法二:动态规划
由于在解法一中需要重复递归计算前两个数据,因此考虑用数组保存计算得到的f(n),此时会需要消耗内存空间。动态规划的状态转移方程:F(N) = F(N - 1) + F(N - 2)。
public int fib(int n) {
if(n==0) return 0;
int[] array=new int[n+1];
array[0]=0;
array[1]=1;
for(int i=2;i<=n;i++) {
array[i]=(array[i-1]+array[i-2])%1000000007;
}
return array[n];
}
- 解法三:循环取余法(题解区解法)
取余规则运算: (a + b) % p = (a % p + b % p) % p ,因此可以边运算边取模。
public int fib(int n) {
int a=0, b=1, sum;
for(int i=0;i<n;i++) {
sum = (a+b)%1000000007;
a=b;
b=sum;
}
return a;
}
青蛙跳台阶问题
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
解析
这道题本质上是求斐波那契数列的第n项(仅仅是初始值不同)。这样理解:
- 当n==1时,只有一种跳法,即f(1)=1,
- 当n==2时,可以从零级台阶上直接跳两步上来,也可以从一级台阶上跳一步上来,共有2种跳法,即f(2)=2,
- 当n==3时,可以从一级台阶上跳两步上来,也可以从二级台阶上跳一步上来,即总共有f(3)=f(2)+f(1)种跳法,
- 同理:有n级台阶时,可以从(n-1)级台阶上跳一步上来,也可以从(n-2)级台阶上跳两步上来,总共有f(n)=f(n-1)+f(n-2)种跳法。
因此:题目可用数学化公式描述为:f(0)=1,f(1)=1,f(n)=f(n-1)+f(n-2)(当n>=2时)
。
public int numWays(int n) {
if(n==0 || n==1) return 1;
int[] array = new int[n+1];
array[0]=1;
array[1]=1;
for(int i=2;i<=n;i++) {
array[i]=(array[i-1]+array[i-2])%1000000007;
}
return array[n];
}
public int numWays(int n) {
int a=1,b=1,sum;
if(n==0 || n==1) return a;
for(int i=2;i<=n;i++) {
sum = (a+b)%1000000007;
a=b;
b=sum;
}
return b;
}