0 题目
现在要求输入一个整数n,输出斐波那契数列的第n项。
1 分析
传统递归实现,需要求多个重复子问题。
使用动态规划,memo记录,但是,只是用了两个。
因此改进冬天规划
2 实现
普通的动态规划
int Fibonacci(int n) { vector<int> memo = {0, 1}; for (int i = 2; i <= n; ++i) { memo.push_back(memo[i - 2] + memo[i - 1]); } return memo[n]; }
使用三个int不停的交换
int Fibonacci(int n) { if (n == 0) { return 0; } if (n == 1) { return 1; } int a = 0, b = 1; int m = 0; //交换用的。 int i; // 0,1的时候已经输出了,因此这里从2开始 for (i = 2; i <= n; i++) { m = a + b; a = b; //保持a永远是第一个 b = m; //b永远是第二个 } return m; }
3 拓展
3.1 题目
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
分析,f(n)=f(n-1)+f(n-2)
f(i)跳到第i层可能的方法。
f(0)=0
f(1)=1
f(2)=2
f(3)=f(2)+f(1) 也就是说,从f(2)调到f(3),和从f(1)调到f(3)
因此,与斐波那契数列不同之处在于,这个题目是从第三个开始的有地推公式的。
int jumpFloor(int number) { if (number == 1) { return 1; } else if (number == 0) { return 0; } int f1 = 0; int f2 = 1; int ret = 0; for (int i = 1; i <= number; ++i) { ret = f1 + f2; f1 = f2; f2 = ret; } return ret; }
3.2 题目
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
同上一个题,只不过,这次真的需要memo了
int jumpFloorII(int number) { vector<int> memo(number + 1, 1); for (int i = 1; i <= number; ++i) { for (int j = 1; j < i; ++j) { memo[i] += memo[j]; } } return memo[number]; }
3.3 题目
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
f(0)=0
f(1)=1
f(2)=f(0)+f(1)
在于怎么铺,只有一个的时候,只有一种铺法。当连个2*1的时候,就有横竖两种了。因此,嗯,借用了上一个的状态。
int rectCover(int number) { if (number == 1) { return 1; } else if (number == 0) { return 0; } int f1 = 0; int f2 = 1; int ret = 0; for (int i = 1; i <= number; ++i) { ret = f1 + f2; f1 = f2; f2 = ret; } return ret; }