[LeetCode]70.爬楼梯
解法一 动态规化
假设 f ( x ) f(x) f(x)为爬到第x层台阶时的方法数,通过举例观察可知:
f(1) | f(2) | f(3) | f(4) |
---|---|---|---|
1 | 2 | 3 | 4 |
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
f(n) = f (n-1) + f(n-2)
f(n)=f(n−1)+f(n−2)
所以可以使用动态规化求解:
class Solution {
public int climbStairs(int n) {
if(n==1)return 1;
int[] dp = new int[n];
//初始化f(1)f(2)
dp[0] = 1; dp[1]=2;
for(int i = 2; i < n; i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n-1];
}
}
时间复杂度为
O
(
n
)
O(n)
O(n),空间复杂度为
O
(
n
)
O(n)
O(n)
通过观察可知
f
(
n
)
f(n)
f(n)只跟之前两个状态有关因此可以滚动数组进一步优化空间复杂度为
O
(
1
)
O(1)
O(1)
class Solution {
public int climbStairs(int n) {
if(n==1)return 1;
if(n==2)return 2;
//初始化p,q,r
int p = 1, q = 2, r = 3;
for(int i = 3; i < n; i++){
p = q;
q = r;
r = p + q;
}
return r;
}
}
解法二 通项公式的矩阵形式
通过通项公式可以把该问题转化为求矩阵幂,最后求解的答案为m11
class Solution {
public int climbStairs(int n) {
int[][] M ={{0,1},{1,1}};
int[][] res = pow(M,n);
return res[1][1];
}
//二分法求矩阵n次幂
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;
}
//实现2*2矩阵乘法
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++){
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
}
}
return c;
}
}