细说剑指offer(2)_变态跳台阶之不变态

1. 题外话

1.1 什么叫递推式

如果一个规律(数学题、编程题),可以利用递推的思想去推导出一个公式来解决问题的话。那么这个公式就叫做递推式。

2. 题目描述

2.1 变态跳台阶

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

3.解法1——递归

3.1 代码
public int JumpFloorII(int target) {
        if (target < 2)
            return target;
        
        return JumpFloorII( target - 1) * 2; //推到递推式求出
    }
3.2 分析

代码解读:

  • 此种方法求出此题的递推式是关键,设有以下两个式子。
  • 式子1:f(n) = f(n - 1) + f(n - 2) + ~~~ + f(0)
  • 式子2:f( n - 1) = f(n - 2) + f( n - 2) + ~~~ + f(0)
  • 式子1 - 式子2 得到本题的递推式——f(n) = 2*f(n - 1)
  • 当然f(0) = 0,f(1) = 1
  • 得到递推式后,我们可以选择利用递归的方法求出解。

复杂度解读:

  • 虽然递归的次数不多,但是本身递归方法入栈出栈(线程的方法栈)也会消耗时间空间。勉强算是O(n)。

4. 解法2——算术解法

4.1 代码
public int JumpFloorII(int target) {
        return (int)Math.pow(2, target - 1); //直接2的target - 1次方
    }
4.2 分析

代码解读:

  • 惊讶?no,因为如果我们仔细算f(n)的话,会发现0,1,2,4,8,16尼玛不就是2的次方嘛!当然f(n) = 2*f(n - 1)也提醒你了。

复杂度解读:

  • 运算级别,时间O(1),不过可以再改进下。因为是2的倍数的运算,所以我们可以采用位运算。改为 return 1<<(target - 1);
  • 啥?不知道位运算?建议好好复习下计算机基础。

5. 解法3——动态规划

5.1 代码
public int JumpFloorII(int target) {
        if (target < 2)//不用算啦,直接返回
            return target;
        
        int[] dp = new int[target + 1];// 你想返回dp[target],你确定不多加一格?
        
        dp[0] = 0;
        
        for(int i = 0; i <= target; i++){
            for(int j = i - 1; j > 0; j--){
                dp[i] += dp[j];//dp[n]的跳法等于dp[n - 1] + dp[n - 2] + ~~~+ dp[0]种跳法
            }
            dp[i]++;//本身就有直接跳到n来,所以+1
        }
        
        return dp[target];
    }
5.2 分析

代码解读:

  • 动态规划的思想。台阶为n的解法,是台阶为n-1一直到0的台阶解法的和。所以代码中有两层循环。

复杂度解读:

  • O(n的平方),很慢的一种算法。且有额外的空间消耗。

6 总结

直接运算划得来。递归竟比规划好。奈何规划失人心。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值