70、爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
提示:
1 <= n <= 45
方法一:普通递归(超时)
1.1 思路分析
爬n阶楼梯可以分成爬1阶的方法数+爬n-1阶的方法数。
递归公式如下:
f
(
n
)
=
{
1
,
n
=
1
2
,
n
=
2
f
(
n
−
1
)
+
f
(
n
−
2
)
n
>
2
f(n) = \begin{cases} 1, & n=1 \\ 2, & n=2 \\ f(n-1)+f(n-2) & n > 2 \end{cases}
f(n)=⎩⎪⎨⎪⎧1,2,f(n−1)+f(n−2)n=1n=2n>2
1.2 代码实现
class Solution {
public int climbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
return climbStairs(n-1) + climbStairs(n-2);
}
}
1.3 测试结果
1.4 复杂度
- 时间复杂度:O(2n)
- 空间复杂度:O(n)
方法二:递归 + hashmap
2.1 思路分析
方法一中有许多重复计算,我们可以引入hashmap避免重复计算,每当计算f(k)时,先查看hashmap中是否存在结果,如果存在直接返回,否则进入递归。
2.2 代码实现
class Solution {
private Map<Integer, Integer> storeMap = new HashMap<Integer, Integer>();
public int climbStairs(int n) {
if (n == 1) return 1; // 终止条件:f(1) = 1
if (n == 2) return 2; // 终止条件:f(2) = 2
if (storeMap.get(n) != null){
return storeMap.get(n); // 返回查询结果
} else {
int result = climbStairs(n-1) + climbStairs(n-2);
storeMap.put(n, result);
return result;
}
}
}
2.3 测试结果
2.4 复杂度
- 时间复杂度:O(n)
- 空间复杂度:O(n)
方法三:循环(非递归)
3.1 思路分析
从图中可以看出,f(3)之后,当前结果等于前两个结果之和。所以定义两个变量存储前两个结果。
3.2 代码实现
class Solution {
public int climbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
int result = 0;
int prev = 1;
int prePre = 2;
for(int i = 3; i <= n; i++){
result = prev + prePre; // f(n)=f(n-1)+f(n-2)
prePre = prev; // f(n-2) = f(n-1)
prev = result; // f(n-1) = f(n)
}
return result;
}
}
3.3 测试结果
3.4 复杂度
- 时间复杂度:O(n)
- 空间复杂度:O(1)