斐波那契数列
《剑指Offer》P73
可用以实现青蛙跳台阶问题,线段问题等
问题拓展:
1、青蛙跳台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
解法:如果第一次跳1级,则方法数等于后面n-1个台阶的总跳法数F(n - 1);
如果第一次跳2级,则方法数等于后面n-2个台阶的总跳法数F(n - 2);
则n个台阶总的跳法数为F(n) = F(n - 1) + F(n - 2);
2、矩形覆盖问题:最终的计算关系式同上;
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
C++代码:
//较差的实现方式一,里面包涵了很多重复计算
long long Fibonacci::Fibonacci_fun1(int n)
{
if (n <= 0)
{
return 0;
}
if (n == 1)
{
return 1;
}
return Fibonacci_fun1(n - 1) + Fibonacci_fun1(n - 2);
}
//直接使用循环来实现
long long Fibonacci::Fibonacci_fun2(int n)
{
//不能忽略n为1,2的情况
if (n < 0)
{
return 0;
}
int temp[] = {0,1};
if (n < 2)
{
return temp[n];
}
long long temp1 = temp[0];
long long temp2 = temp[1];
long long result = 0;
for (int i = 2; i <= n;i ++)
{
result = temp2 + temp1;
temp1 = temp2;
temp2 = result;
}
return result;
}
Java实现:
1)迭代实现:
public class Solution {
public int Fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int pre = 0; int cur = 1;
for (int i = 1; i < n; i++) {
int temp = cur;
cur += pre;
pre = temp;
}
return cur;
}
}
2)优化的递归算法:
// 使用结果集来缓存所有结果
int[] fb = new int[N];
public int Fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
if (fb[n] != 0) return fb[n];
return (fb[n] = Fibonacci(n - 1) + Fibonacci(n - 2));
}
2、青蛙跳台阶问题拓展:
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
则解法同上F(n) = F(n - 1) + F(n - 2) + ....+ F(n - n); (F(0) = 1);
要解上式,使用递归法是不明智的,可以考虑使用一个长度为n的数组来记录每一个n对应的值,然后进行迭代即可。
public class Solution {
public int JumpFloorII(int target) {
if (target <= 0)
return 0;
// 使用一个数组将每个递归值记录下来即可
int[] data = new int[target];
for (int i = 0; i < target; i++) {
data[i] = 1; // 注意此初始化值
for (int j = 0; j < i; j ++)
data[i] += data[j];
}
return data[target - 1];
}
}