Leetcode热题70:爬楼梯
题目如下:
假设需要爬一个n阶的楼梯,每次都可以选择爬1阶或者2阶,问有多少种方式?
示例1:n = 2
总共有两种情况:
①:1 + 1 = 2
②:2 = 2
示例2:n = 3
总共有三种情况:
①:1 + 1 + 1 = 3
②:1 + 2 = 3
③:2 + 1 = 3
分析:不妨多列举几种情况,假设n = 4,此时有如下可能
①:1 + 1 + 1 + 1 = 4
②:1 + 1 + 2 = 4
③:1 + 2 + 1 = 4
④:2 + 1 + 1 = 4
⑤:2 + 2 = 4
总共五种情况
当n = 5时,
①:1 + 1 + 1 + 1 + 1 = 5
②:1 + 1 + 1 + 2 = 5
③:1 + 1 + 2 + 1 = 5
④:1 + 2 + 1 + 1 = 5
⑤:2 + 1 + 1 + 1 = 5
⑥:1 + 2 + 2 = 5
⑦:2 + 1 + 2 = 5
⑧:2 + 2 + 1 = 5
如果现在有n阶楼梯,我们令f(n)表示有几种可能,因此,根据上文列举的一些情况,可以得到如下表格:
n | f(n) |
---|---|
1 | 1 |
2 | 2 |
3 | 3 |
4 | 5 |
5 | 8 |
… | … |
我们不难发现,f(1) = 1, f(2) = 2,往后f(n) = f(n -1) + f(n - 2)
因此,就是一个斐波那契数列,使用递归实现,代码如下:
let climbStairs = n => {
if(n === 1) return 1
else if(n == 2) return 2
else return climbStairs(n - 1) + climbStairs(n - 2)
};
但是这种写法时间复杂度过高,假设n = 10,此时第一次递归返回的应该是climbStairs(9) + climbStairs(8),而在处理climbStairs(9)时会得到climbStairs(8) + climbStairs(7),这里发现climbStairs(8)重复计算了2次,会产生2个climbStairs(7),发现climbStairs(7)会重复计算3次!
为了解决这种重复计算带来的时间复杂度,可以优化考虑使用空间换时间,使用一个数据存储之前已经计算过的值,代码如下:
let climbStairs = n => {
let fibonacci = [1, 2]
for(let i = 2; i < n; i++) {
fibonacci.push(fibonacci[i - 2] + fibonacci[i - 1])
}
return fibonacci[n - 1]
}
这种方法与dp类似,转移方程为dp[i] = dp[i - 1] + dp[i - 2]