跳台阶问题分析

问题描述:

一个台阶,一次可以跳3级或者5级,跳到第n级有多少种跳法。

问题分析:

刚开始的思路是,每次跳3级或者5级,不一定能跳到第n级,要求n是3的倍数,或者是5的倍数,或者是3i和5j的和(i>=0,j>=0)。所以考虑三种情况:

1、  n是3的倍数;

2、  n是5的倍数;

3、  3i+5j=n(i>=0且j>=0)。其他情况则是不可到达第n级。

情况1和情况2很容易,直接求倍数就可以。情况3考虑的是两层for循环,使用蛮力法找到满足条件的i和j的值。后来发现,情况1和情况2不需要在算法中写具体实现,不满足情况1和情况2,不可到达第n级,则跳法为0。

  另一种是递归。递归要满足两个条件:1、存在相同的情景,可以重复调用;2、存在最终的结束条件。

  最终的结束条件很容易想到,那就是最后只剩下3级台阶或者5级台阶的情况,一次可以跳完,只有一种跳法。相同的情景可以这么考虑,开始跳之前,还剩下n级台阶没有跳过,跳过一次后,比如跳3级或者5级,则剩下n-3或者n-5,再开始第二次跳,发现第二次跳和第一次跳面临的选择是相同的,也是跳3级或者5级,只是要跳的台阶数减少了3级或者5级。那么每次的跳是相同的情景,可以重复调用。如果用函数jumpCount(n)计算跳法的话,n级台阶的跳法即是jumpCount(n),按照递归的思路,如果第一次跳3级的话,则剩下n-3,再跳这n-3级台阶,这n-3级台阶的跳法是jumpCount(n-3)。同理,如果第一次跳5级的话,则剩下n-5级的跳法是jumpCount(n-5);以此递推,每次都是在剩下的台阶数中跳3级或者5级,剩下n-3或者n-5,再重复跳,一直到最后只剩下3级或者5级。那么n级台阶的跳法是jumpCount(n)= jumpCount(n-3)+ jumpCount(n-5)。其实这里发现和第一种思路的第3中情况是类似的。

这里当时有个思想误区,首先确实是考虑到了将剩下的台阶数作为下次跳跃的总数,每次跳跃进行递归的调用。但是受第一种思路的影响,每次都在考虑n-3i或者n-5j的情况,没有想到递归的核心思想是整体与局部的思想,问题分大的模块来看待,每个小模块再一步一步细分。每个大模块和小模块是相似的关系。每个小模块只需要考虑一步,不需要考虑整体情况,所以不需要考虑i和j了。

问题验证:

蛮力法代码:

 1     /**
 2      * 思路一:非递归,蛮力法找到满足条件的值
 3      * @param n 待跳的台阶数
 4      * @return 跳法
 5      */
 6     public static int jumpCount1(int n) {
 7         int count = 0;//跳法
 8         //i最大不能超过n的约数,同理j
 9         for (int i = 0; i <= n / 3; i++) {
10             for (int j = 0; j <= n / 5; j++) {
11                 if (3 * i + 5 * j == n) {
12                     count++;//满足条件,则找到了一种跳法
13                 }
14             }
15         }
16
17         return count;
18     }

递归代码:

 1     /**
 2      * 思路二:递归
 3      * @param n 待跳的台阶数。每次跳3级或者5级
 4      * @return 跳法
 5      */
 6     public static int jumpCount(int n) {
 7         if (n < 3) {
 8             return 0;//如果小于3,则跳不了
 9         }
10
11         if (n == 3 || n == 5) {
12             return 1;//只剩下3级或者5级,则只有一种跳法,跳3级或者5级,一次跳完
13         }
14
15         return jumpCount(n - 3) + jumpCount(n - 5);//每次跳跃,剩下为n-3或者n-5,作为下次待跳跃的台阶数
16     }

蛮力法时间复杂度为O(n^2),递归为O(n),递归时间复杂度优于蛮力法。递归算法明显优于蛮力法,简介清晰,但是数据量大的情况下运行效率较低,内存开销大。

总结:

1、  蛮力法很容易想到,思想误区是要跳出判断是否能跳到第n级台阶的情况,这种情况跳法就是0,不需要代码中判断。

2、  递归法要牢牢抓住递归的思想,考虑整体就不要管部分,考虑部分就不要管整体。

时间: 2024-11-12 03:08:33

跳台阶问题分析的相关文章

变态跳台阶

题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级--它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 思路:每个台阶都有跳与不跳两种情况(除了最后一个台阶),最后一个台阶必须跳.所以共用2^(n-1)中情况 思路二: 一行代码 return  1<<--number; 思路三 关于本题,前提是n个台阶会有一次n阶的跳法.分析如下: f(1) = 1 f(2) = f(2-1) + f(2-2)         //f(2-2) 表示2阶一次跳2阶的次数. f(3) = f(

跳台阶问题

给定一个有N个台阶的楼梯,一个人从下到上开始跳台阶,这个人有两种跳的方式:一次跳一个台阶,一次跳两个台阶: 问:从台阶底端跳到台阶顶端,有多少种跳台阶的方式? 解法一:递归法 分析: 首先我们考虑最简单的情况.如果只有1个台阶,那么显然只有一种跳法:如果是2级台阶,那么有2种跳法.对于一个有n级台阶的楼梯来说,我们设跳法为 f(n) ,假如我们先跳1个台阶,则剩下有 n-1 个台阶,跳法为 f(n-1) 次,假如我们先跳2个台阶,则剩下 n-2 阶,跳法为 f(n-2):由此可以推出,对于一个n

剑指OFFER之变态跳台阶(九度OJ1389)

题目描述: 一只青蛙一次可以跳上1级台阶,也可以跳上2级--它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入包括一个整数n(1<=n<=50). 输出: 对应每个测试案例, 输出该青蛙跳上一个n级的台阶总共有多少种跳法. 样例输入: 6 样例输出: 32 解题思路: 这道题目跟之前的跳台阶大同小异,只是跳台阶的阶数从1变到了n,也就是说,不再是跳一下或者跳两下的问题,而是跳n下的问题.那么解题的思路显然还得逆向分析,我们

(原)剑指offer跳台阶和矩形覆盖

跳台阶 时间限制:1秒空间限制:32768K 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 分析同样为斐波那契数列边形这样的题肯定有公式 设n级台阶,总跳法 jumps n jumps 1 1 2 2 3 3 4 5 5 8 猜测 fbonicc(n) = fbonicc(n-1) + fbonicc(n-2) 3 4 5 111 1111 1111(1) 21  211  211(1) 12  121 121(1) 112 112(1)

斐波那契数列及青蛙跳台阶问题

题目1: 写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项. 斐波那契(Fibonacci)数列定义例如以下: f(n)=?????0,1,f(n?1)+f(n?2),n=0n=1n>2 效率非常低的解法: 递归解法(效率非常低) long long Fibonacci_Solution1(unsigned int n) { if(n <= 0) return 0; if(n == 1) return 1; return Fibonacci_Solution1(n - 1) +

牛客网青蛙变态跳台阶问题

function jumpFloorII(number) { // write code here var result = [0,1,2]; var methodNum = 0; var n1 = 1; var n2 = 2; var temp = 0; if(number <=0){ return 0; }else if(number === 1){ return 1; }else if(number === 2){ return 2; }else{ /*for(var i = 3;i <

Solution 27:跳台阶问题

问题描述 一个台阶有n级,一次可以跳1级或者2级.问共有多少种跳法?分析算法的时间复杂度. 解决思路 假设f(n)代表n级台阶的跳法数目,其递推式如下: 当n=1时,f(n)=1; 当n=2时,f(n)=2; 其他,f(n)=f(n-1)+f(n-2) 那么有如下几种解决方法: 1. 递归,指数级时间复杂度: 2. 循环,O(n)时间复杂度,O(1)空间复杂度: 3. dp,O(n)时间复杂度,O(n)空间复杂度: 程序 见Fibonacci题:http://www.cnblogs.com/ha

[剑指OFFER] 斐波那契数列- 跳台阶 变态跳台阶 矩形覆盖

跳台阶 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. class Solution { public: int jumpFloor(int number) { if(number == 1) return 1; if(number == 2) return 2; int n1 = 1; int n2 = 2; int rtn = 0; for(int i = 3; i <= number; i++) { rtn = n1 + n2; n1 = n2;

动态规划题目(二)——跳台阶

动态规划题目(二)--跳台阶 1. 题目描述 一个台阶总共有n 级,如果一次可以跳1 级,也可以跳2 级. 求总共有多少总跳法,并分析算法的时间复杂度. 2. 递归方式 对于这个动态规划问题,我们一样分两步来想: 假如我们跳了1级,那么剩下的跳法就是f(n-1): 假如我们跳了2级,那么剩下的跳法就是f(n-2): 这个时候我们就可以递归实现了,慢!我们还需要跳出递归的条件,这个也是必不可少的! 这个题目而言,跳出递归的条件是当n==1, 2的时候,我们返回1, 2. 为什么是1,2呢?因为当n