【前言】坚持日更LeeCode刷题系列
不积跬步,无以至千里;不积小流,无以成江海。愿与诸君共勉!
【题目】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 阶
【概论】:是不是有部分朋友觉得这题十分熟悉??接下来,我将从不同的角度来打开这题的新视野(部分思路参考自LeeCode官方以及评论区前辈)。
思路一:
利用递归的思想,每次都将爬1阶或2阶的情况进行组合。在每一次的模拟中,我们都调用函数来进行,并返回爬1阶和2阶楼梯函数的值之和。具体代码如下:
def climb(i,n):
if(i>n):
return 0
elif(i==n):
return 1
else:
return climb(i+1,n) + climb(i+2,n)
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
return climb(0,n)
没看懂?没关系,下面给出n=5时的结构图你就懂了。
图片来源于LeeCode。
很显然其中进行了很多重复的调用,这种解法显然是不优的。
运行结果:提交未通过,出现了超时
错误。
思路二:
有了前面的理解,那么我们很清晰的意识到第i次的方法数与第i-1次和第i-2次有关,因为每次都只能爬1或2阶,因此当在第i个台阶时,它的起点只能为i-1或i-2阶,因此其满足climb[i] = climb[i-1]+climb[i-2]的关系。具体代码如下:
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
map1 = {} #思考下用字典做存储的好处
map1[1] = 1
map1[2] = 2
for i in range(3,n+1):
map1[i] = map1[i-1] + map1[i-2]
return map1[n]
运行结果:
关于其中一些知识的链接:
动态规划图解(漫画版)
思路三:
在上一个思路中,我给出了climb[i]=climb[i-1]+climb[i-2]的表达式,是不是有朋友已经想到了斐波拉契数列,或者在此之前就已经想到了这种解法,那么它和动态规划又有什么不同呢?其具体代码如下:
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n<=2:
return n
else:
first = 1
second = 2
for i in range(3,n+1):
third = first + second
first = second
second = third
return second
运行结果:
当我们用first、second、third三个变量代替原有的存储结构时,空间复杂度显然降低了,但它和动态规划在时间复杂度上相等。
思路四:
官方还给出了第一种思路的改进解法–记忆递归;还给出了
斐波拉契公式,Binets 方法数学解题思路,有兴趣的朋友可以通过下方链接自行了解。
关于其中一些知识的链接:
官方题解
分享就到这里了,欢迎大家一起交流讨论。
注明
:
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs/