【题目】
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
【示例 1】
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
【示例 2】
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。 - 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
【代码】
【方法一:动态规划】
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+3,0);
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++)
dp[i]=dp[i-1]+dp[i-2];
return dp[n];
}
};
dp[i]=dp[i-1]+dp[i-2];可优化,详情见方法三
【时间效率很高】
class Solution {
public:
int climbStairs(int n) {
int pre=0,now=0,next=1;
for(int i=1;i<=n;i++){
pre=now;
now=next;
next=pre+now;
}
return next;
}
};
【方法一的优化:Binet’s Formula】
执行用时:
0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:
34.9 MB, 在所有 Java 提交中击败了98.45%的用户
class Solution {
public:
int climbStairs(int n) {
double sqrt5=sqrt(5);
return (int)((pow((1+sqrt5)/2,n+1)-pow((1-sqrt5)/2,n+1))/sqrt5);
}
};
【矩阵快速幂】
public class Solution {
public int climbStairs(int n) {
int[][] q = {{1, 1}, {1, 0}};
int[][] res = pow(q, n);
return res[0][0];
}
public int[][] pow(int[][] a, int n) {
int[][] ret = {{1, 0}, {0, 1}};
while (n > 0) {
if ((n & 1) == 1)
ret = multiply(ret, a);
n >>= 1;
a = multiply(a, a);
}
return ret;
}
public int[][] multiply(int[][] a, int[][] b) {
int[][] c = new int[2][2];
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for(int k = 0; k < 2; k++)
c[i][j] += a[i][k] * b[k][j];
return c;
}
}