leetcode 的第70题 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例2:
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
提示:
1 <= n <= 45
爬到楼顶从逆向思维来看,可以理解为从楼顶下来,每次只能下一楼或者下两楼,以n=6为例,第一步我们有两种走法,要么下到5楼,要么下到4楼,那么从6楼下来的方法数这个问题的求解就变为从5楼下来的方法数+从4楼下来的方法数,那么问题规模得到了减小,以此寻找递归的灵感。
由下图可以看出退出递归的条件,当在一楼时,只要一种方法,在二楼时,有1+1,2这两种方法。
通过自顶向下的求解方式得到6楼下来的方法数。
# python3
class Solution:
def climbStairs(self, n: int) -> int:
if n == 1:
return 1
elif n == 2:
return 2
else:
return Solution.climbStairs(self,n-1)+Solution.climbStairs(self,n-2)
但出现了超时的错误,因此需要改进
我们继续从这张图寻找线索
但我们计算6楼的下楼方法时,可以转化为求从5楼和4楼的下楼方法,但是,计算从5楼的下楼方法时,我们已经计算了4楼的下楼方法,但之后又把4楼的下楼方法计算了一遍,并且越在树的下端,越是一些重复计算。浪费了很多时间。
因此,找到了可以进行优化的地方。
可以把重复计算的值先存储下来,再碰到时就直接调用,可以利用hash map进行存储,在python中,可以利用字典进行hash map的实现。
# python3
'''
在递归执行的过程中很多东西被重复计算,浪费了时间
如果f(k)被计算过了,可以将值保存到hash map中
再次碰到f(k)直接重hash map 中调用
python中可以利用dict实现hash map的功能
'''
class Solution1:
hash_map = dict()
def climbStairs(self, n: int) -> int:
if n == 1:
return 1
if n == 2:
return 2
if None != self.hash_map.get(n):
return self.hash_map.get(n)
else:
result = Solution.climbStairs(self,n-1)+Solution.climbStairs(self,n-2)
self.hash_map[n] = result
顺利通过了测试
用递归的方法可以自顶向下求解,那么是否又非递归的方法计算。
重新查看这张图
f(1)+f(2)得到了f(3)
而f(4)=f(3)+f(2)
之后f(5)=f(4)+f(3)
最后得到f(6)=f(5)+f(4)
通过两个变量存储之间的中间结果,不断更新累加就能得到最终结果
# python3
'''
非递归方法,用循环,自底向上累加
'''
class Solution2:
def climbStairs(self, n: int) -> int:
if n == 1:
return 1
if n == 2:
return 2
result = 0
temp1 = 2
temp2 = 1
for i in range(3,n+1):
result = temp1 + temp2
temp2 = temp1
temp1 = result
return result
成功通过测试,并且循环的方式时间复杂度为O(n),通过时间确实比递归短。