经典递归问题:青蛙跳台阶,跳1个,2个或者3个

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经典递归问题:青蛙跳台阶,跳1个,2个或者3个相关的知识,希望对你有一定的参考价值。

这个问题经常在各类面试中看到。一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

我们知道如果要写递归代码,那一定要先找到递归公式,这个找法,一个是画执行时的栈结构图来看,一个是从小到大来分析。我们看一下从小到大的过程:

 

从这里我们可以归纳出,递推公式是f(n)=f(n-1)+f(n-2),然后就可以根据三步走策略来写代码了:

1、确定递归函数功能

假设 f(n) 的功能是求青蛙跳上一个n级的台阶总共有多少种跳法,代码如下:

int f(int n)

2、找出递归结束的条件

求递归结束的条件,直接把 n 压缩到很小很小就行了,因为 n 越小,我们就越容易直观着算出 f(n) 的多少,所以当 n = 1时,你知道 f(1) 为多少吧?够直观吧?即 f(1) = 1。代码如下:

int f(int n)
    if(n == 1)
        return 1;
    

3.找出函数的等价关系式

每次跳的时候,青蛙可以跳一个台阶,也可以跳两个台阶,也就是每次跳的时候,小青蛙有两种跳法。

第一种跳法:第一次我跳了一个台阶,那么还剩下n-1个台阶还没跳,剩下的n-1个台阶的跳法有f(n-1)种。

第二种跳法:第一次跳了两个台阶,那么还剩下n-2个台阶还没,剩下的n-2个台阶的跳法有f(n-2)种。

所以,小青蛙的全部跳法就是这两种跳法之和了,即 f(n) = f(n-1) + f(n-2)。至此,等价关系式就求出来了。于是写出代码:

int f(int n)
    if(n <=2 )
        return n;
    
    return f(n-1) + f(n-2);

代码看上去没问题对不对?其实是有和斐波那契数列一样的问题的,当 n = 2 时,显然会有 f(2) = f(1) + f(0)。我们知道,f(0) = 0,按道理是递归结束,不用继续往下调用的,但我们上面的代码逻辑中,会继续调用 f(0) = f(-1) + f(-2)。这会导致无限调用,进入死循环。

关于递归结束条件是否够严谨问题是递归算法的重要一环,有很多人在使用递归的时候,由于结束条件不够严谨,导致出现死循环。我们这里再补充n=2的情况就行了,代码如下:

int f(int n)
    //f(0) = 0,f(1) = 1,等价于 n<=2时,f(n) = n。
    if(n <= 2)
        return n;
    
    return f(n-1) + f(n-2);

那结束条件该怎么确定呢?其实最简单的方式就是写几个试一试,n足够小的时候也不过为 0 1 2 3 这几个种情况,或者是执行结束或者开始的时候几个元素,带进去试一试看看对不对就行了。

如果一次还能跳3个呢?

拓展如果这里说青蛙每次可以跳1个,2个,或者3个,那该怎么做呢?

一共有n个台阶,那青蛙第一次可以有几种跳法呢?很显然第一次可以选择跳1个,2个,3个,那剩余的台阶数是多少呢?是n-1,n-2,n-3个。而剩余台阶不管是多少个,都可以按照f(n)一样的逻辑来处理,也就是f(n-1)+f(n-2)+f(n-3)。所以我们就得到了递推公式f(n)=f(n-1)+f(n-2)+......+f(n-3)。这明显也是一个递归过程。

我们前面说了,必须处理结束时的场景,所以f(0),f(1),f(2)都要单独标记一下,所以最终代码就是:

int jump(int n)
  if(n<=2)return n;
  return f(n-1)+f(n-2)+f(n=3);

以上是关于经典递归问题:青蛙跳台阶,跳1个,2个或者3个的主要内容,如果未能解决你的问题,请参考以下文章

青蛙跳台阶衍生之变态跳台阶(递归,思路分析及代码实现)

青蛙跳台阶问题。

C语言递归:汉诺塔问题和青蛙跳台阶问题

递归经典:汉诺塔问题和青蛙跳台阶的三个问题(爆肝的数学推理步骤以及详细代码)

汉罗塔与青蛙跳台阶的递归实现(及扩展青蛙跳台阶)C语言从入门到入土(入门篇)(算法篇p2)

递归2之对青蛙跳台阶和斐波那契数列的思考