【编程-剑指offer】跳台阶问题

4、跳台阶问题

问题描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)

该问题课可以引申为
问题1:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
问题2:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
问题3:一只青蛙一次可以跳上1级、5级、10级台阶,求该青蛙跳上一个n级的台阶总共有多少种跳法。

解析

动态规划

假设f(n)是n级台阶的跳法,首先以简单的情况来说,
如果
n=1,f(n)=1 (1);
n=2,f(n)=2 (1-1,2);
n=3,f(n)=3 (1-1-1,2-1,1-2)······

n级对应的问题的解来源于n级的上一步所在的层级,比如,对于问题1,n级可能是上一次所处的层级跳了1级或2级,所以f(n)=f(n-1)+f(n-2),以此类推:

  1. 对于问题1,有公式:f(n)=f(n-1)+f(n-2), n>=2,即为一个斐波那契数列,需要用动态规划逐步求出f(0),f(1)…
  2. 对于问题2,有公式:f(n)=f(n-1)+f(n-2)+…f(0), f(n-1)=f(n-2)+f(n-3)+…+f(0),综合起来得,f(n)=2^n,不需要用动态规划,直接套公式
  3. 对于问题3,有公式:f(n)=f(n-1)+f(n-5)+f(n-10), n>=10,需要用动态规划,逐步求出f(0),f(1),f(2)…直到最后需要的f(n)

代码块

问题1可以看作斐波那契数列的求解问题
1、自顶向下的动态规划–递归
这是最简单的实现方法,也是最低级的做法,耗费的时间是输入规模的指数级别的。

class Solution {
public:
    int jumpFloor(int number) {
        if(number<=0) return 0;
        if(number==1) return 1;
        if(number==2) return 2;
        return jumpFloor[number-1]+jumpFloor[number-2];
    }
};

2、自底向上的动态规划
是最普通的动态规划方法,线性时间复杂度即可得到结果。

class Solution {
public:
    int jumpFloor(int number) {
        int a[number+1];
        if(number<=0) return 0;
        if(number==1) return 1;
        if(number==2) return 2;
        a[1]=1;
        a[2]=2;
        for(int i =3;i<=number;i++){
            a[i] = a[i-1] + a[i-2];
        }
        return a[number];
    }
};

3、备忘录方法
这也是一种自底向上的动态规划,与递归方法基本一致。唯一的区别是这里采用了一个数组来记录每个子问题的解,从而避免重复求解,将问题简化。

class Solution {
public:
    int jumpFloor(int number) {
        int a[number+1];
        if(number<=0) return 0;
        if(number==1) return a[1] = 1;
        if(number==2) return a[2] = 2;
        a[number] = jumpFloor[number-1]+jumpFloor[number-2];
        return a[number];
    }
};

动态规划求解的问题的一般要具有3个性质:

(1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

(2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。

(3) 有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)

拓展

问题4:矩形覆盖:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

猜你喜欢

转载自blog.csdn.net/qq_20135597/article/details/82417493