爬楼梯
题目
假设你正在爬楼梯。需要 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层呢?如果一次只能爬一步或两步,那么爬第n层要么是从n-1上来,要么是从n-2上来.所以kn(n) = kn(n-1) + kn(n-2)
- 递归优化
在递归的时候将重复递归的值存储下来,比如10会有9和8,9有8和7,应该缓存8.这样可以节省开销
- 动态规划
递归是从后往前,我们可以从前往后分析
既然dp[n]=dp[n-1]+dp[n-2]
那么dp[3]=dp[1]+dp[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);
}
}
- 递归优化
class Solution {
//缓存
private int[] memo;
public int climbStairs(int n) {
memo = new int[n + 1];
return getClimbStairs(n);
}
private int getClimbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
if (memo[n] == 0) memo[n] = getClimbStairs(n - 1) + getClimbStairs(n - 2);
return memo[n];
}
}
- 动态规划
public int climbStairs(int n) {
//动态规划
int[] mount = new int[n+1];
mount[0] = 1;
mount[1] = 2;
for(int i = 2;i < n;i++){
mount[i] = mount[i-1]+mount[i-2];
}
return mount[n-1];
}
- 动态规划优化
class Solution {
public int climbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
int a1 = 1, a2 = 2, a3 = 0;
while (n-- > 2) {
a3 = a1 + a2;
a1 = a2;
a2 = a3;
}
return a3;
}
}