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

思路

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

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

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

n − 1 n-1 n1阶再爬 1 1 1阶或者从 n − 2 n-2 n2阶再爬 2 2 2阶。

LeetCode刷题——70. 爬楼梯_第1张图片

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

LeetCode刷题——70. 爬楼梯_第2张图片
用同样的思路可以求出爬 n − 1 n-1 n1阶和爬 n − 2 n-2 n2阶的方法数。从上面这个递归树可以看出,存在很多重复子问题。

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

代码

递归

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刷题——70. 爬楼梯_第3张图片
虽然思路是对的,但是递归的方式是比较低效的,这里导致了计算超时。参阅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]

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

LeetCode刷题——70. 爬楼梯_第4张图片

你可能感兴趣的:(#,动态规划,在线编程,#,斐波那契数列,动态规划,leetcode,70.爬楼梯)