Leetcode70--爬楼梯

本文围绕Leetcode70爬楼梯问题展开,该问题是给定n阶楼梯,每次可爬1或2个台阶,求到达楼顶的方法数。作者作为算法小白,介绍了递归和动态规划两种解题思路,还分享了自己首次解题时用排列组合的方法,使用Python语言实现。

Leetcode70–爬楼梯

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

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

编程语言:python

作者:黑暗主宰

邮箱:shengzhanhe@gmail.com

Leetcode70–爬楼梯

题目描述

原题链接:

​ https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode/ (中文)

​ https://leetcode.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode/ (英文)

题目描述:

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

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

注意:

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

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

解题思路

博主是一个算法小白,也是通过刷Leetcode来提升自己的编程思维。

对于爬楼梯这道理,第一想到的是排列组合,然后通过一波分析,提交也通过了。然后又参考别人的想法,恍然大悟,原来还可以这样解题。下面就先写递归和动态规划的方法,然后在放出我当时第一次做这个题的code。下文中的图片链接来自于LeetCode官方题解1

方法1:递归

为什么用递归可以做呢,首先逆向思维的分析这道题,如果总共有5个台阶,我们已知登上第4个台阶有 m m m种走法,登上第3个台阶有 n n n种走法,那么登上第5个台阶是不是就有 m + n m+n m+n种走法;有小伙伴说,第4个台阶到第5个台阶是有 m m m种,第3个台阶到第5个台阶不是有 m + 1 m+1 m+1种吗?(那是因为,已知第3个台阶和第4个台阶的走法,从第3个台阶可以走1 阶 + 1 阶,也可以走2 阶,但是走1 阶 + 1 阶这种方法属于第4台阶的方法,所以总体来说是 m + n m+n m+n)。同理,如下图所示,我们只要知道第1阶和第2阶,就能知道第3阶,以此类推。其实说白了,本质上就是一个斐波那契数列,代码如下

在这里插入图片描述

def climbStairs(n):
    if n == 1:
        return 1
    if n == 2:
        return 2
    return climbStairs(n-1) + climbStairs(n-2)

这种方法效率很低,从上图可以看出,随着递归的加深,需要更多的空间去存储数据,并且时间复杂度指数增长。

方法2:动态规划

通过上文的分析可以总结公式
d p [ i ] = d p [ i − 1 ] + d p [ i − 2 ] dp\left[ i \right] = dp\left[ {i - 1} \right] + dp\left[ {i - 2} \right] dp[i]=dp[i1]+dp[i2]
更好的理解,如下图所示在这里插入图片描述

对应代码如下:

def climbStairs(n):
    res = [0, 1]
    for i in range(n):
        res[0], res[1]= res[1], res[0] + res[1]
        
	return res[-1]

然后,下面的代码是第一次做这个题时的解法,大佬勿喷

经过一波分析(😜),可以计算2和1的组合计算总共有多少种方法,先计算最多可以有多少个2,然后余下的就是1的数量,然后每次减少一个2,就会增加两个1,组合公式为
c ( m , n ) = m ! n ! × [ m − n ] ! c\left( {m,n} \right) = \frac{{m!}}{{n! \times \left[ {m - n} \right]!}} c(m,n)=n!×[mn]!m!
然后把每次组合累加,就是总共多少种方法啦。

def climbStairs(self, n):
 	if n == 1:
		return 1
	two_nums = n//2
	one_nums = n%2
	cnt = 0
        
	nums = two_nums + one_nums
	while two_nums:
		denominator = 1
		tmp1 = two_nums
		while tmp1:
			denominator *= tmp1
			tmp1 -= 1
		numerator  = 1
		tmp2= two_nums
		tmp3 = nums
		while tmp2:
			numerator *= tmp3
			tmp2 -= 1
			tmp3 -= 1
		cnt += numerator//denominator
		two_nums -= 1
		nums += 1
	cnt += 1
	return cnt

欢迎大家关注我的个人公众号,同样的也是和该博客账号一样,专注分析技术问题,我们一起学习进步
在这里插入图片描述

注: 文中有写错的地方,欢迎大家不吝指正!!!


  1. https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode ↩︎

<think>我们被要求回答LeetCode70题“爬楼梯”的解题思路,重点在动态规划和递归方法。根据引用内容,我们可以总结如下:1.问题描述:爬楼梯,每次可以爬12个台阶,到达第n阶有多少种不同的方法。2.动态规划是解决此问题的典型方法,状态转移方程为:dp[i]=dp[i-1]+dp[i-2]。3.递归方法虽然直观,但存在重复计算,可能导致超时,可以使用记忆化搜索优化(Top-DownDP)。4.动态规划(自底向上)通常使用数组存储中间结果,然后进行空间优化(例如用两个变量代替数组)。我们将按照以下结构组织回答:一、问题描述二、思路分析(递归关系)三、递归方法(及优化)四、动态规划方法(及优化)五、总结同时,根据要求,我们需要在回答末尾生成相关问题。注意:所有数学表达式(包括变量、方程)使用$...$格式,独立公式使用$$...$$格式。回答使用中文。引用标识:在引用的内容末尾添加[^1]、[^2]等,但注意我们引用的内容来自用户提供的引用[1]到[4]。</think>### LeetCode 70爬楼梯|动态规划与递归解析 #### 一、问题描述 给定楼梯阶数 $n$,每次可爬 $1$ 或 $2$ 阶,求到达第 $n$ 阶的不同方法总数。 #### 二、核心思路 **状态转移方程**: $$ dp[i] = dp[i-1] + dp[i-2] $$ 其中 $dp[i]$ 表示到达第 $i$ 阶的方法数。该方程源于:第 $i$ 阶只能从 $i-1$ 阶(爬 $1$ 阶)或 $i-2$ 阶(爬 $2$ 阶)到达[^2][^4]。 --- #### 三、动态规划解法(推荐) **自底向上迭代**,避免递归重复计算: ```python def climbStairs(n: int) -> int: if n <= 2: return n # 边界处理 dp = [0] * (n+1) dp[1], dp[2] = 1, 2 # 初始状态 for i in range(3, n+1): dp[i] = dp[i-1] + dp[i-2] # 状态转移 return dp[n] ``` **空间优化**(滚动变量): 仅需存储前两个状态,空间复杂度优化至 $O(1)$: ```python def climbStairs(n: int) -> int: if n <= 2: return n a, b = 1, 2 # a=dp[i-2], b=dp[i-1] for _ in range(3, n+1): a, b = b, a + b # 更新状态 return b ``` --- #### 四、递归解法(需优化) **基础递归**(不推荐): 直接实现状态方程,但存在指数级重复计算: ```python def climbStairs(n: int) -> int: if n == 1: return 1 if n == 2: return 2 return climbStairs(n-1) + climbStairs(n-2) # 递归分解 ``` **问题**:计算 $dp[5]$ 需重复计算 $dp[3]$ 和 $dp[4]$,时间复杂度 $O(2^n)$,$n=45$ 时超时[^3]。 **优化:记忆化搜索(Top-Down DP)** 添加缓存避免重复计算,时间复杂度降为 $O(n)$: ```python def climbStairs(n: int) -> int: memo = {} # 记忆字典 def dfs(k): if k <= 2: return k if k not in memo: memo[k] = dfs(k-1) + dfs(k-2) # 缓存结果 return memo[k] return dfs(n) ``` --- #### 五、复杂度对比 | 方法 | 时间复杂度 | 空间复杂度 | 适用性 | |---------------|------------|------------|----------------| | 基础递归 | $O(2^n)$ | $O(n)$ | 仅小 $n$ | | 记忆化搜索 | $O(n)$ | $O(n)$ | 需额外缓存 | | 动态规划 | $O(n)$ | $O(n)$ | 通用 | | **空间优化DP**| $O(n)$ | $O(1)$ | **最优解** | > **总结**:动态规划(尤其空间优化版)是本题最佳解法。其本质是斐波那契数列问题,状态转移方程 $dp[i]=dp[i-1]+dp[i-2]$ 是核心[^1][^2]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值