目录
【前言】
今天刚刚上了本学期第一节算法设计与分析课,这个老师是去年刚刚入职我们学校的,这节课主要是一个算法概述和图灵机的简单了解。其中他在课程的开始,给出一道题目,是一个青蛙跳台阶的题目,据说这道题目是在老师刚刚本科毕业的时候,去人人网面试时遇到的题目,也算是一道经典面试题了,课堂上老师只给出了简单的思路,课下我把这道题自己写了一遍,并且进行了拓展。
【题目描述】
一只青蛙一次可以跳 1 级台阶,也可以跳 2 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
【思路一——递归】
根据上述枚举可以发现:第 n 阶的跳法 = 第 n-1 阶的跳法 + 第 n-2 阶的跳法
f ( n ) = f ( n - 1 ) + f ( n - 2 )
那么可以得到递归代码如下:
#include<iostream> using namespace std; int n; int step(int n) { if (n == 0) //0阶的时候只有一种跳法,就是不跳 return 1; if (n == 1) return 1; if (n == 2) return 2; return step(n - 1) + step(n - 2); } int main() { cin >> n; int m=step(n); cout << m; }
【递归算法的缺陷】
递归的算法的执行效率很低,因为递归的实现是通过调用函数本身,函数调用的时候,每次调用时要做地址保存,参数传递等,这是通过一个递归工作栈实现的。
具体是每次调用函数本身要保存的内容包括:局部变量、形参、调用函数地址、返回值。那么,如果递归调用N次,就要分配N局部变量、N形参、N调用函数地址、N返回值,这势必是影响效率的,同时,这也是内存溢出的原因,因为积累了大量的中间变量无法释放。
但是递归代码更加紧凑,比非递归的代码更容易去编写和理解。
【思路二——for循环】
为解决上述递归算法的缺点,这里采用for循环实现一遍,思路和递归类似。
采用代码如下:
#include<iostream> using namespace std; #define N 10000000 int n; int a[N]; int main() { cin >> n; a[0] = 1; a[1] = 1; for (int i = 2; i <= n; i++) a[i] = a[i - 1] + a[i - 2]; cout << a[n]; }
【改写题目一——可以跳上n级台阶】
一只青蛙一次可以跳 1 级台阶,也可以跳 2 级……也可以跳上 n 级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
采用递归代码如下:
#include<iostream> using namespace std; int n; int step(int n) { if (n == 0) return 1; if (n == 1) return 1; if (n == 2) return 2; return 2*step(n - 1) ; } int main() { cin >> n; int m = step(n); cout << m; }
采用for循环代码如下:
#include<iostream> using namespace std; #define N 10000000 int n; int a[N]; int main() { cin >> n; a[0] = 1; a[1] = 1; for (int i = 2; i <= n; i++) a[i] = a[i - 1] *2; cout << a[n]; }
【改写题目二——跳上m阶台阶】
一只青蛙一次可以跳 1 级台阶,也可以跳 2 级……也可以跳上 n 级台阶。求该青蛙跳上一个 m 级的台阶总共有多少种跳法。
(1)当n>=m时,则跟跳上n级台阶算法相同;
return 2*step(m - 1) ;
(2)当n<m时:(下面例子假设n=3,m>n)
采用递归代码如下:
#include<iostream> using namespace std; int n,m; int step(int n, int m) { if (m == 0) return 1; if (m == 1) return 1; if (m == 2) return 2; if (m > n) return 2 * step(n,m-1) - step(n, m - 1 - n); if (m <= n) return 2 * step(n, m - 1); } int main() { cin >> n; cin >> m; cout << step(n, m); }
【小插曲】
这个算法的老师我在去年的时候见过他诶,他当时刚刚博士毕业,来我们部门借博士服,我当时跟他简单交流了一下,我当时还问他是博士后嘛,他说他成功留校了。因为他是搞大数据的嘛,没想到他会来教我们人工智能的算法课,啊哈哈哈,真是一次奇妙的经历。。。。
其实这道题还可以用动态规划的方法来做,但是鉴于在写这篇文章的时候,我还没有学动态规划哈哈哈,那就在之后的动态规划的文章中再涉及这道题好啦!
完结撒花!