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 阶

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs

思路

对于这样一个问题,我们先来思考下能否递归的解决,它内部是否有递归的结构。

我们自顶向下的思考问题,直接考虑第nn阶台阶,并且假设它下面的n1n-1阶,n2n-2阶等子问题都已经解决了。

如果我们要想爬上nn阶台阶,因为一次要么爬11阶,要么爬22阶,所以爬nn阶台阶有两种可能。

n1n-1阶再爬11阶或者从n2n-2阶再爬22阶。

在这里插入图片描述

不难看出这是一个递归问题,我们把问题转换为爬n1n-1阶有多少种方法和爬n2n-2阶有多少种方法。然后把这两个问题的答案相加就好了。这样把一个大的问题转换为两个小问题。

在这里插入图片描述
用同样的思路可以求出爬n1n-1阶和爬n2n-2阶的方法数。从上面这个递归树可以看出,存在很多重复子问题。

下面我们先写出按照这种思路解决问题的递归算法。

代码

递归

class Solution:
    def climbStairs(self, n: int) -> int:
        # 递归的终止条件
        if n == 1:
            return 1
        if n == 2:
            return 2
        return self.climbStairs(n-1) + self.climbStairs(n-2)

在这里插入图片描述
虽然思路是对的,但是递归的方式是比较低效的,这里导致了计算超时。参阅LeetCode刷题之动态规划思想,我们可以将其改成记忆化搜索的方式,解决重叠子问题。

因为爬2阶台阶有2种方法,和斐波那契数列很像。这里的递归终止条件还可以写成

if n == 0:
    return 1
if n == 1:
   return 1

这样这个问题就是斐波那契数列的应用。

记忆化搜索

dp = {}

class Solution:
    def climbStairs(self, n: int) -> int:
        # 递归的终止条件
        if n == 0:
            return 1
        if n == 1:
            return 1
        if n not in dp: # 如果没有计算过再去计算
            dp[n] =  self.climbStairs(n-1) + self.climbStairs(n-2)
        return dp[n]

在这里插入图片描述
最后改成动态规划也就很简单了。

动态规划

class Solution:
    def climbStairs(self, n: int) -> int:
        if n == 1:
            return 1
        dp = [1] * (n+1) #dp[0] = 1   ,    dp[1] = 1   ,dp[2]以后的通过下面的式子计算
        
        for i in range(2,n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]

动态规划不需要递归求解,是一种自底向上的求解思想。

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章