Leetcode 70:爬楼梯(最详细的解法!!!)

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

**注意:**给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶

示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶

解题思路

这个问题很简单,对于第n阶台阶有多少种爬法这个问题,我们只需要知道n-1阶和n-2阶有多少种爬法就可以了(第n阶台阶,无非是通过n-1n-2阶台阶爬上去的)。

class Solution:
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        return 1 if n == 0 or n == 1 else self.climbStairs(n - 1) + self.climbStairs(n - 2)

但是这样的写法超时了,因为我们上面算法中存在了大量的重复运算,例如对于求解n=4,我们实际上对n=2的子问题重复计算。以此类推,当数值越大,我们重复元素个数就会越多。我们可以通过记忆化搜索的方式来优化这个问题。

class Solution:
    def _climbStairs(self, n, climb):
        if n == 0 or n == 1:
            return 1

        if n not in climb:
            climb[n] = self._climbStairs(n - 1, climb) + self._climbStairs(n - 2, climb)

        return climb[n]

    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        climb = dict()
        return self._climbStairs(n, climb)

我们通过一个dict记录我们递归过程中计算过的值,只要这个值我们计算过,那么直接返回就好了。

当然这个问题也可以通过动态规划来解决

class Solution:
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        climb = dict()
        climb[0], climb[1] = 1, 1
        for i in range(2, n + 1):
            climb[i] = climb[i - 1] + climb[i- 2]

        return climb[n]

同时这也是迭代的一种写法。实际上这个问题是斐波那契数列的变形,所以我们可以写出这样非常简洁的代码。

class Solution:
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        x, y = 1, 1
        for _ in range(n):
            x, y = y, x + y

        return x

但是上面这种写法的运行速度不如前面的动态规划。实际上你也可以写出一个generator 。

def climbStairs(max): 
    n, a, b = 0, 1, 1 
    while n < max: 
        yield b 
        a, b = b, a + b 
        n = n + 1 

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值