【LeetCode】70.爬楼梯

题目

假设你正在爬楼梯,需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶,你有多少种不同的方法可以爬到楼顶呢?

题解

方法1:基本递归

算法

基本递归即初学递归时所学的最简单、最直观的方法。
假设你爬了 n 段楼梯,则爬上当前楼梯所拥有的方法数是爬上 n-1 段楼梯的方法数加上爬上 n-2 段楼梯的方法数。

代码

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

分析

此方法最简单、直观、易懂,逻辑也很清晰。
但底层的数字被大量重复计算,很容易超时。

  • 时间复杂度: O ( 2 n ) O(2^n) O(2n)
  • 空间复杂度: O ( n ) O(n) O(n)
    n=5时的递归树

图源LeetCode官方题解


方法2:记忆化递归

算法

鉴于基本递归会大量重复计算底层数字,那么我们可以想到,不妨将计算过的数字存起来,需要的时候先看是否已经计算,算过的直接取出来,没有算过的计算,这样每个数字都只会计算一次。

代码

class Solution {
public:
    int climb(int n, int mem[]) {
        if (n == 1 || n == 2)
            return n;
        if (mem[n - 1] == 0)
            mem[n - 1] = climb(n - 1, mem) + climb(n - 2, mem);
        return mem[n - 1];
    }
    int climbStairs(int n) {
        int *mem = new int[n] {0};
        return climb(n, mem);
    }
};

分析

通过维护一个mem数组,将算过的数字从第3个空间开始存起来,前两个空间位置本来应该放第1、2个楼梯的方法数,但不便于创建时指定,故干脆空着了。
mem[i - 1] 等于0,表明位置 i-1 的方法数没算出来,需要计算。最后返回 mem[i - 1] 就行了。

  • 时间复杂度: O ( n ) O(n) O(n),可以满足LeetCode不超时
  • 空间复杂度: O ( n ) O(n) O(n)

方法3:斐波那契循环

算法

其实从前面的解题思路可以得知,爬楼梯本质上就是斐波那契数列。故我们可以使用循环计算斐波那契。

代码

class Solution {
public:
    int climbStairs(int n) {
        if (n == 1 || n == 2)
            return n;
        int a = 1, b = 2, t;
        for (int i = 0; i < n - 2; i++) {
            t = b;
            b += a;
            a = t;
        }
        return b;
    }
};

分析

之所以是 for (int i = 0; i < n - 2; i++) ,是因为要比n少循环2次,这个可以代入3来理解:计算3的时候只需要循环一次即可,故3减去2即得1。
该算法时间复杂度为 O(n) ,需要从前往后计算n次,空间复杂度只有 O(1) ,因为没有动态创建空间。


动态规划

算法

可以看出,这个问题得最优解可从它的子问题得最优解得出,即:
i 个楼梯最多方法数 = 第 i-1 个楼梯最多方法数 + 第 i-2 个楼梯最多方法数:
dp[i] = dp[i - 1] + dp[i - 2]

代码

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

分析

由于每一次的最优解都取决于前两次的最优解,故从前往后得出所有楼梯的最优解并存在dp数组中,大体上跟上面的斐波那契数列算法非常相似,时间复杂度与空间复杂度均为 O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值