【经典面试题——青蛙跳台阶】【递归/for循环做法】【跳上n级台阶】【跳上m级台阶】

目录

【前言】

【题目描述】

【思路一——递归】

【思路二——for循环】

【改写题目一——可以跳上n级台阶】

【改写题目二——跳上m阶台阶】

【小插曲】


【前言】

        今天刚刚上了本学期第一节算法设计与分析课,这个老师是去年刚刚入职我们学校的,这节课主要是一个算法概述和图灵机的简单了解。其中他在课程的开始,给出一道题目,是一个青蛙跳台阶的题目,据说这道题目是在老师刚刚本科毕业的时候,去人人网面试时遇到的题目,也算是一道经典面试题了,课堂上老师只给出了简单的思路,课下我把这道题自己写了一遍,并且进行了拓展。


【题目描述】

        一只青蛙一次可以跳 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);
}

【小插曲】

        这个算法的老师我在去年的时候见过他诶,他当时刚刚博士毕业,来我们部门借博士服,我当时跟他简单交流了一下,我当时还问他是博士后嘛,他说他成功留校了。因为他是搞大数据的嘛,没想到他会来教我们人工智能的算法课,啊哈哈哈,真是一次奇妙的经历。。。。

        其实这道题还可以用动态规划的方法来做,但是鉴于在写这篇文章的时候,我还没有学动态规划哈哈哈,那就在之后的动态规划的文章中再涉及这道题好啦!

完结撒花!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值