爬楼梯(递归、哈希表.......)

目录

先上题目

方法一:递归

方法二:哈希表

方法三:动态规划

先上题目

 

方法一:递归

        现在让 n = 6 ,假设我们站在六楼,现在我们往楼下走,每次可以向下走一阶或两阶,那么我们走的方法就变成了第一次走一阶的总方法数加上第一次走两阶的总方法数 ,用式子表达就是 f(5) + f(4) , f(4) 和 f(5) 的解法同理。f(5) = f(4) + f(3) , f(4) = f(3) + f(2) .......

        我们可以得到表达式 : f( n ) = f( n - 1 ) + f( n - 2 )。同时分析题目得到两个基本条件 :

f( 1 ) = 1  、 f( 2 ) = 2 。

        所以我们可以写出递归的代码,但是!!! 注意,用递归的方法时间复杂度为 O(n^2)(原因在方法二会提到)提交上去大概率会超时,所以这个思想大家了解就好,代码和斐波那契数列的代码几乎一样。后面我们会说到更好的解法。

方法二:哈希表

        提醒喔,这个方法我用Java写的。还没了解到Java的同学可以先跳过这里喔。

        通过上面的图我们不难发现,每一层中都出现了重复计算过的数据,这就造成了方法一的局限性,所以我们可以用哈希表存储每次前面没有计算过的结果,当下次再需要计算的时候,先在哈希表中找一下看前面有没有计算过。

        这里我们再简单介绍一下Java中 HashMap 的几个常用方法:

    

         下面展示代码:

class Solution {
    private Map<Integer,Integer> storeMap = new HashMap<>();
    public int climbStairs(int n) {
        if (n == 1)
            return 1;
        if (n == 2)
            return 2;
        if (null != storeMap.get(n))
            return storeMap.get(n);
        else{
            int result = climbStairs(n - 1) + climbStairs(n - 2);
            storeMap.put(n , result);
            return result;
        }
    }
}

方法二的时间复杂度为 O(n)

方法三:动态规划

        通过前面的分析,我们得到了方程  f( n ) = f( n - 1 ) + f( n - 2 ),同时我们去找边界条件,发现f( 0 ) = 1  、 f( 1 ) = 1.因为动态规划使用数组下标时需要从 0 开始。下面展示代码(因为C语言的动态数组比较麻烦,所以这里就用Java写了):

class Solution {
    public int climbStairs(int n) {
       int []dp = new int [n + 1];
       dp[0] = 1;
       dp[1] = 1;
       for (int i = 2 ; i <= n ; ++i){
           dp[i] = dp[i - 1] + dp[i - 2];
       }
       return dp[n];
    }
}

时间复杂度为O(n)。

        下面我们再通过滚动数组思想对上面代码进行优化:(这里用的C,因为没有用到具体的数组)

int climbStairs(int n){
    if ( n == 1)
        return 1;
    if ( n == 2)
        return 2;
    int result = 0;
    int pre = 2;
    int prePre = 1;

    for (int i = 3 ; i <= n ; i++){
        result = pre + prePre;
        prePre = pre;
        pre = result;
    }
    return result;
}

时间复杂度也是 O(n)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不怕娜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值