Leetcode刷题日记-No70爬楼梯

题目地址

https://leetcode.cn/problems/climbing-stairs/

思路1:递归

        递归的关键是找到递归公式递归终止条件。假设f(n)为爬到n阶楼顶所需的方法数,又限制每次可以爬1或者2个台阶,n阶只能是从n-1阶或者n-2阶跳上去的,假设f(n-1)和f(n-2)已知,那么就有f(n)=f(n-1)+f(n-2),这就是递归公式。再考察递归终止条件,即一些简单的基本情况,很容易可以以得出:f(1)=1,f(2)=2。总结一下:

  1. 递归公式:f(n)=f(n-1)+f(n-2)
  2. 递归终止条件:f(1)=1f(2)=2

        将上述公式转换为代码:

class Solution {
    public int climbStairs(int n) {
        if(n == 1 || n == 2) {
            return n;
        }
        return climbStairs(n-1)+climbStairs(n-2);
    }
}

        提交后显示计算超时:

        这也是递归解法经常出现的一个问题,用一张图来看下问题出在哪里(假设n=6):

        可以看到, f(3)、f(4)的值均出现了重复计算。而且随着n的增加,重复计算的节点数会变得更多,会大大增加计算时间,这也就是出现运行超时的原因。这里递归的时间复杂度大约是O(n^{2})

思路2:迭代

        既然递归方法会出现重复计算,那么我们尝试使用迭代法避免这个重复计算的问题。与递归自上而下逐层返回相反,迭代法采用自下而上的方式计算,计算方式还是:f(n)=f(n-1)+f(n-2)。代码如下:

class Solution {
    public int climbStairs(int n) {
        if(n == 1 || n == 2) {
            return n;
        }
        int cur = 2;
        int prev = 1;
        for(int i=3;i<=n;i++) {
            cur = cur + prev;
            prev = cur - prev;
        }
        return cur;
    }
}

        提交结果:

        还是以n=6为例分析迭代法的执行过程:

i

cur

prev

2

2

1

3

3

2

4

5

3

5

8

5

6

13

8

        可以看到每次循环都会计算当前i层的方法数,且在下次循环中作为prev直接参与计算,无需再次计算,从而避免了重复计算的问题。迭代运算包含一层循环,时间复杂度是O(n)

思路3:空间换时间

        递归中出现的重复计算问题,还有一种空间换时间的解法思路,具体来讲:新增一个Hash表用于存储每个节点的结果。在自上而下的递归过程中,每遇到一个新的节点,先不着急往下递归,而是做一个判断,该节点是否已经存在于Hash表中,如果存在直接获取结果;否则计算结果并保存在Hash表中。代码如下:

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

        提交结果:

         这里的时间复杂度同样是O(n),但是引入了Hashmap存储中间结果,因此有O(n)的空间复杂度。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值