题目描述:
You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Note: Given n will be a positive integer.
Example 1:
Input: 2
Output: 2
Explanation: There are two ways to climb to the top.
- 1 step + 1 step
- 2 steps
Example 2:
Input: 3
Output: 3
Explanation: There are three ways to climb to the top.
- 1 step + 1 step + 1 step
- 1 step + 2 steps
- 2 steps + 1 step
题目大意:
- 给定一个正整数n,代表着阶梯的高度,你每次登阶梯的方式有两种,一个是,一次迈一步,一个是,一次迈两步
- 让你返回每次都有哪几种可能的方式,登上阶梯顶
解题思路:
- 第一种思路,递归解法
- 由题意可知,当给你一个正整数n时,不管n多大,你每次都有两种选择,是迈一步还是迈两步,也就是假如当n=3时,如题目的例子所示,f(3) = f(3-1) + f(3-2) ,f(3) 表示,n=3时,你所能选择的登顶的方式,那么它只能由前一种状态,选择迈一步,或者迈两步
- 当最后的状态为零时,也就是这种迈步选择方式,真的可以登顶,如果小于零,说明这种方式不行,无法匹配
- 递归树见下图
- 如果直接按照上图的递归树,编写代码,就是暴力解法,肯定能出答案
- 但是这里可以更巧妙一些,使递归这种可能包含了很多冗余的重复计算,比如图中的深蓝色部分,如果暴力解法,那这部分,显然就被计算了两次,不划算
- 在这里,用备忘录(memo)解决这个重复计算
- 思路是,定义一个字典,用来装每次递归都计算了哪些过程,下次再递归时,先别着急去递归,先去备忘录里面,看看,这个过程有没有被计算过,如果有,那别递归了,太慢,因为都要触底才能向上返回值,直接返回那个存在备忘录里的值
- 典型的空间换时间,自顶向下解法
少废话,上代码:
class Solution:
def climbStairs(self, n):
memo = {}#定义备忘录,用来记录已经计算过的递归树的分支,避免重复计算
def recursion(n):
#先去备忘录里看看,算没算过,算过了,直接返回那个算过的值
if n in memo:
return memo[n]
if n == 0:#base case,基础值
return 1
if n < 0:#无效方式
return 0
memo[n] = recursion(n-1) + recursion(n-2)#每次只有两种选择,上一层台阶还是上两层,递归下去
return memo[n]#返回那个最后的计算结果
return recursion(n)
运行时间和内存占用:
- Runtime: 40 ms, faster than 5.95% of Python3 online submissions for Climbing Stairs.
- Memory Usage: 13.8 MB, less than 5.97% of Python3 online submissions for Climbing Stairs.
别着急,还可以更快
- 上动态规划
- 了解的朋友都知道,首先定义dp数组的含义,一定要清晰明确,不然后根本没法进行,不知道的朋友,没关系,看完,你也会了
- 我的想法是,直接dp[i] 代表着给定的i层阶梯,所可能达到的所有方式
- 比如dp[1]=1,代表给定的1层阶梯,登顶的可能方式有1种
- dp[2]=2,以此类推
- 其实前面两步,已经将基础案例,也就是base case,给出来了,有了这两个,那么下面无论给定n多大,都可以直接通过for循环,依次加到那个n值
- 因为是这样,dp[3]等于什么?一定要有这种递推关系,一旦找到,此题一般KO,dp[3]=dp[3-1]+dp[3-2],还是那句话,每次就两种选择,要么迈一步,要么迈两步
- 想想斐波纳契数列中的定义,和本题是否异曲同工?
少废话,上代码:
class Solution:
def climbStairs(self, n):
#定义dp数组并明确概念,dp[i]代表登上i层台阶可能有的所有迈步方式
dp = []
dp.append(0)#空着不用,主要是方便数值相互对应上,偏于理解
dp.append(1)#加初值,base case
dp.append(2)#同理
if n == 1:
return 1
if n == 2:
return 2
if n > 2:
for i in range(3, n+1):#开始遍历,由递推关系,逐步推出想要结果
sum = dp[i-1] + dp[i-2]
dp.append(sum)
return dp[-1]#最后一个数,即为结果
运行时间和内存占用:
- Runtime: 32 ms, faster than 26.09% of Python3 online submissions for Climbing Stairs.
- Memory Usage: 14 MB, less than 5.97% of Python3 online submissions for Climbing Stairs.