斐波那契
什么是斐波那契数列
斐波那契数列是个啥,其实就是个数列:0、1、1、2、3、5、8、13、21、34.......,总结下来就是从第三数开始就是前两个数的和。那么为什么要介绍它呢,因为它能衍生出很多实际中的问题,同时,在解决问题的同时,正好把时间复杂度和空间复杂度在复习一下。
介绍斐波那契数列的三种实现方法,输出第n数
方法一:递归
斐波那契数列的公式为:f[n] = f[n-1] + f[n-2], 初始值f[0]=0, f[1]=1,目标求f[n]。
int Fibonacci(int n) {
if (n==0 || n==1) return n;
return Fibonacci(n-1) + Fibonacci(n-2);
}
此方法为最垃圾的方法,没有之一。时间复杂度o(2^n),空间o(1);时间消耗性能太长。
方法二:记忆化搜索
int Fib(int n, vector<int>& dp) {
if (n==0 || n==1) return n;
if (dp[n] != -1) return dp[n];
return dp[n] = Fib(n-1) + Fib(n-2);
}
int Fibonacci(int n) {
vector<int> dp(45, -1); // 因为答案都是>=0 的, 所以初始为-1,表示没计算过
return Fib(n, dp);
}
时间复杂度o(n),空间o(n);
方法三:动态规划
int Fibonacci(int n) {
if (n == 0 || n == 1) return n;
int a = 0, b = 1, c;
for (int i=2; i<=n; ++i) {
c = a + b;
a = b;
b = c;
}
return c;
}
嘿嘿,只需要三个变量,也只要循环一次;时间复杂度o(n),空间o(1);那面试的问你,斐波那契数列怎么实现,你菊花一紧,直接说出了第三种方案,人家面试官此时就有问号了,本想你来个些个复杂度较高的,然后再问你有没有优化方案的,来体现自己面试才能的时候,你直接把路堵死了,后面不得拿出更难的算法考你?
下面再问一道题目:
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
不要懵,分析一下,假设f[i]表示在第i个台阶上可能的方法数。逆向思维。如果我从第n个台阶进行下台阶,下一步有2种可能,一种走到第n-1个台阶,一种是走到第n-2个台阶。所以f[n] = f[n-1] + f[n-2],是否闻出一点熟悉的味道,那不就是斐波那契数列;
再来一道题目:
来点空间想象,走一步可以用一个矩形,或者两个矩形,这不就是那味吗,那不还是斐波那契;
最后来一道收尾:
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
此时我相信你已经对斐波那契数已经熟悉了,还特码用思考,这不斐波那契直接解决了,那我得恭喜你答错了。你没发现,它后面多了句话吗,它也可以跳上n级,所以f[n] = f[n-1] + f[n-2]+f[n-3]+f[n-4]+.......+f[1];想了想,这个好像是递归,但是怎么用算法表示呢,撸破头皮想了想,f[n-1] = f[n-2]+f[n-3]+f[n-4]+.......+f[1],那么f[n] = 2 * f[n-1] =2 * 2 * f[n-2]=...........=2^(n-1) * f[1];
于是最终有2^(n-1) 种跳法。
您学废了吗?