剑指Offer (九):跳台阶问题进阶版(Java版)

问题,一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

 

这个问题明显是由跳台阶进阶而来,我们由于已经做过跳台阶问题,先进行简单分析。

首先可知,第一阶台阶只会有一种跳法;,第二阶可能有两种跳法,分别为两次一步、一次两步两种。

  • 若楼梯阶级 n = 3

    • 跳 1 步到 3:剩下的是第二步没跳,起始跳到第二步只有两种种

    • 跳 2 步到 3:,剩下的是第一步没跳,起始跳到第一步只有一种

    • 跳 3 步到 3:剩下0步没跳,所以只有一种跳法

  • 所以得出结论,若三级台阶,则跳法一共有 1 + 1 + 2 = 4种,可以得出以下结论

    f(3) = f(2) + f(1) + 1;

当然,我们还可以继续分析台阶级数为四,为五的情况,最终可以通过分类讨论,得出以下结论:

  • 若楼梯阶级 n (n >= 3)

    • 跳 1 步到 n:剩下的是第 n - 1 步没跳,起始跳到第 n - 1 步设它为 pre1 种

    • 跳 2 步到 n:剩下的是第 n - 2 步没跳,起始跳到第 n - 2 步设它为 pre2 种

    • 跳 3 步到 n:剩下的是第 n - 3 步没跳,起始跳到第 n - 3 步设它为 pre3 种

    • ....

    • 一直到 跳n-1到n:剩下的是第 1 步没跳,起始跳到第 n - 1 步就只有一种跳法。

  • 最终得出以下结论

    • f(n) = f(n-1) + f(n-2) +...+ f(1) + 1;

    • f(n -1) = f(n-2) +...+ f(1) + 1;

    • 两者相减 则 f(n) - f(n -1) = f(n-1) -> f(n) = 2f(n-1);

  • 得到计算公式,f(n) = 2f(n-1) (n >=2 ),得到公式以后,解决方案就变得很简单了。

所以解决方案也有两者方法,一种递归,一种利用公式进行循环运算。

第一种解决方案,便是采用递归的方式,代码如下

public static int firstJumpFloorN(int target) {
        if(target < 0){
            return 0;
        }
        if(target == 1){
            return 1;
        }
        return firstJumpFloorN(target - 1 ) * 2;
    }

第二种便是类似于斐波拉契数列,代码如下

public static int  secondJumpFloorN(int target) {
        if(target < 0){
            return 0;
        }
        if(target == 1){
            return 1;
        }
        int one = 1;
        int two = 2;
        for (int i = 2; i <= target; i++){
            two = one * 2;
            one = two;
        }
        return two;
    }

完整代码如下

public class MainJumpFloorN {

    public static void main(String[] args) {

    }

    /**
     * 递归调用
     * @param target
     * @return
     */
    public static int firstJumpFloorN(int target) {
        if(target < 0){
            return 0;
        }
        if(target == 1){
            return 1;
        }
        return firstJumpFloorN(target - 1 ) * 2;
    }

    /**
     * 累加调用
     * @param target
     * @return
     */
    public static int  secondJumpFloorN(int target) {
        if(target < 0){
            return 0;
        }
        if(target == 1){
            return 1;
        }
        int one = 1;
        int two = 2;
        for (int i = 2; i <= target; i++){
            two = one * 2;
            one = two;
        }
        return two;
    }


}

剑指offer 牛客网原文地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值