【原题】
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?Note: Given n will be a positive integer.
【翻译】
爬楼梯时可以一次爬一层或者两层,问要到达第n层,有多少种方法?n为正整数。
【解题思路】
设爬上第n层楼梯有S(n)种方法,那么爬上第n-1层楼梯有S(n-1)种方法,再爬一层就到达第n层;爬上第n-2层楼梯有S(n-2)种方法,再爬两层就到达第n层;最后一步不一样,所以是两种不一样的方法,此时斐波那契数列派上用场了。S(n)=S(n-1)+S(n-2), n为正整数,其中S(1)=1, S(2)=2, S(3)=3, ......
(1)递归
两个递归调用,加法运算的次数仍然是斐波那契数列,导致时间复杂度呈指数级。结果超时。
class Solution {
public:
int climbStairs(int n) {
if (n==1||n==2)
return n;
else
return climbStairs(n-1)+climbStairs(n-2);
}
};
(2)迭代
做n-1次加法运算,没有必要特意使用一个数组来存储斐波那契数列中的前面元素,为了完成该任务,只需要存储两个元素就足够了。时间复杂度O(n),空间复杂度O(1)。
class Solution {
public:
int climbStairs(int n) {
int f[10000];
f[1]=1;
f[2]=2;
for(int i=3; i<=n; i++){
f[i]=f[i-1]+f[i-2];
}
return f[n];
}
};
【其他解法】
(1)利用公式
class Solution {
public:
int climbStairs(int n) {
double s = sqrt(5);
return floor((pow((1+s)/2, n+1) + pow((1-s)/2, n+1))/s + 0.5);
}
};
(2)利用方阵的快速幂
基于等式:当n>=1时,,比如
,
,.......
class Solution {
public:
//Fibonacci数列
int climbStairs(int n) {
if(n == 0){
return 0;
}
int A[2][2] = {1,1,1,0};
//初始为单位矩阵
int Matrix[2][2] = {1,0,1,0};
//n = n - 1;
for(; n ;n >>= 1){
//奇偶
if(n&1){
MatrixMulti(Matrix,A);
}//if
MatrixMulti(A,A);
}//for
return Matrix[0][0];
}
private:
//矩阵乘法
void MatrixMulti(int matrix[2][2],int matrix2[2][2]){
int a = matrix[0][0] * matrix2[0][0] + matrix[0][1] * matrix2[1][0];
int b = matrix[0][0] * matrix2[0][1] + matrix[0][1] * matrix2[1][1];
int c = matrix[1][0] * matrix2[0][0] + matrix[1][1] * matrix2[1][0];
int d = matrix[1][0] * matrix2[0][1] + matrix[1][1] * matrix2[1][1];
matrix[0][0] = a;
matrix[0][1] = b;
matrix[1][0] = c;
matrix[1][1] = d;
}
};