70.爬楼梯
假设你正在爬楼梯。需要 阶你才能到达楼顶。
每次你可以爬 或 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 是一个正整数。
示例 1:
输入:
输出:
解释: 有两种方法可以爬到楼顶。
- 阶 + 阶
- 阶
示例 2:
输入:
输出:
解释: 有三种方法可以爬到楼顶。
- 阶 + 阶 + 阶
- 阶 + 阶
- 阶 + 阶
解答1
此题目可以说是最经典(另一种说法是最“容易”)的动态规划的题目。
动态规划是将一个大问题分解为多个简单的子问题来求解的方法。
动态规划常常适用于有重叠子问题与最优子结构的问题。
思路
- 设为总的方法数量
- 可以看到,到第阶的方法其实一共有两种方式
- 从第阶爬一步到达第阶
- 从第阶爬两步到达第阶
- 因此可以总结出公式
可以发现,这个就是斐波那契数列的变种。
代码1
java实现
class Solution {
public int climbStairs(int n) {
return resolve(n);
}
public int resolve(int n) {
if (n==1) {
return 1;
}
if (n==2) {
return 2;
}
return resolve(n-1)+resolve(n-2);
}
}
代码非常的简洁,马上丢到leetcode上跑一次,居然执行了10801 ms。击败了0.98%的人。。。
解法2
解法1虽然勉强能跑,但是有一个非常严重的问题是,重复计算量过大。
但是因为并没有暂存的地方,导致被计算了两次。
此时考虑到以往的数据会被重复使用,那么何不做一个数组暂存数据呢。
代码2
java实现
class Solution {
public int climbStairs(int n) {
int[] cache = new int[n+1];
return resolve(n);
}
public int resolve(int n, int[] cache) {
if (n==1) {
return 1;
}
if (n==2) {
return 2;
}
if (cache[n] ==0) {
cache[n] = resolve(n-1,cache) +resolve(n-2,cache);
}
return cache[n];
}
}
此方法4ms执行完成。
解法3
上述两种方法,均是递归调用,如何转为迭代呢?
代码3
java实现
class Solution {
public int climbStairs(int n) {
int[] cache = new int[n+1];
cache[0] = cache[1] = 1;
for(int i=2;i<=n;i++) {
cache[i] = cache[i-1] + cache[i-2];
}
return cache(n);
}
}