版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/82776513
假设你正在爬楼梯。需要 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 阶
解题思路
这个问题很简单,对于第n
阶台阶有多少种爬法这个问题,我们只需要知道n-1
阶和n-2
阶有多少种爬法就可以了(第n
阶台阶,无非是通过n-1
或n-2
阶台阶爬上去的)。
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
return 1 if n == 0 or n == 1 else self.climbStairs(n - 1) + self.climbStairs(n - 2)
但是这样的写法超时了,因为我们上面算法中存在了大量的重复运算,例如对于求解n=4
,我们实际上对n=2
的子问题重复计算。以此类推,当数值越大,我们重复元素个数就会越多。我们可以通过记忆化搜索的方式来优化这个问题。
class Solution:
def _climbStairs(self, n, climb):
if n == 0 or n == 1:
return 1
if n not in climb:
climb[n] = self._climbStairs(n - 1, climb) + self._climbStairs(n - 2, climb)
return climb[n]
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
climb = dict()
return self._climbStairs(n, climb)
我们通过一个dict
记录我们递归过程中计算过的值,只要这个值我们计算过,那么直接返回就好了。
当然这个问题也可以通过动态规划来解决
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
climb = dict()
climb[0], climb[1] = 1, 1
for i in range(2, n + 1):
climb[i] = climb[i - 1] + climb[i- 2]
return climb[n]
同时这也是迭代的一种写法。实际上这个问题是斐波那契数列的变形,所以我们可以写出这样非常简洁的代码。
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
x, y = 1, 1
for _ in range(n):
x, y = y, x + y
return x
但是上面这种写法的运行速度不如前面的动态规划。实际上你也可以写出一个generator 。
def climbStairs(max):
n, a, b = 0, 1, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!