题目描述
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?
分析:f(n)=f(n-2)+f(n-1)。
超时递归算法:复杂度2^n
public class Solution {
public int climbStairs(int n) {
if(n<0) return -1;
if(n==1) return 1;
if(n==2) return 2;
return climbStairs(n-1)+climbStairs(n-2);
}
}
普通:复杂度O(n)
public class Solution {
public int climbStairs(int n) {
if(n<0) return -1;
if(n==1) return 1;
if(n==2) return 2;
int pre=1;
int res=2;
int t;
for(int i=3;i<=n;i++){
t=res;
res=res+pre;
pre=t;
}
return res;
}
}
矩阵:O(logn)
public class Solution {
public int climbStairs(int n) {
if(n<0) return -1;
if(n==1) return 1;
if(n==2) return 2;
int t = n-2;
int[][] mat={{1,1},{1,0}};
int[][] res={{1,0},{0,1}};
//i>=0不行,0往右移动一位还是0
for(int i=t;i!=0;i>>=1){
if((i&1)!=0) res=mult(res, mat);
mat=mult(mat, mat);
}
return 2*res[0][0]+res[1][0];
}
//矩阵乘法
@SuppressWarnings("unused")
private int[][] mult(int[][] matA,int[][] matB){
int row = matA.length;
int col = matB[0].length;
int t = matA[0].length;//计算目标矩阵每一位,要做的乘法次数,第一个矩阵的列或第二个矩阵的行
int[][] res = new int[row][col];
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
//目标矩阵的res[i][j];
for(int k=0;k<t;k++){
res[i][j]+=(matA[i][k]*matB[k][j]);
}
}
}
return res;
}
}
对比:
package com.lp;
public class Solution {
/*
* [f(n),f(n-1)] = [f(n-1),f(n-2)]*[{1,1},{1,0}]
* [f(n-1),f(n-2)] = [f(n-2),f(n-3)]*[{1,1},{1,0}]
* ……
* [f(n),f(n-1)] = [f(2),f(1)]*[{1,1},{1,0}]^n-2
*
* 所以答案f(n)就是f(2)*res[0][0]+f(1)*res[1][0];
* 转化为求:[{1,1},{1,0}]^n-2。。矩阵乘法
*/
public int climbStairs(int n) {
if(n<0) return -1;
if(n==1) return 1;
if(n==2) return 2;
int t = n-2;
int[][] mat={{1,1},{1,0}};
int[][] res={{1,0},{0,1}};
//i>=0不行,0往右移动一位还是0
for(int i=t;i!=0;i>>=1){
if((i&1)!=0) res=mult(res, mat);
mat=mult(mat, mat);
}
return 2*res[0][0]+res[1][0];
}
//矩阵乘法
@SuppressWarnings("unused")
private int[][] mult(int[][] matA,int[][] matB){
int row = matA.length;
int col = matB[0].length;
int t = matA[0].length;//计算目标矩阵每一位,要做的乘法次数,第一个矩阵的列或第二个矩阵的行
int[][] res = new int[row][col];
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
//目标矩阵的res[i][j];
for(int k=0;k<t;k++){
res[i][j]+=(matA[i][k]*matB[k][j]);
}
}
}
return res;
}
public static void main(String[] args) {
Solution solution = new Solution();
Long startLong=System.currentTimeMillis();
System.out.println(solution.climbStairs(50000000));
System.out.println("矩阵算法消耗时间:");
System.out.println(System.currentTimeMillis()-startLong);
}
}
输出:
223038178
矩阵算法消耗时间:
1
package com.lp;
public class Test {
public int climbStairs(int n) {
if(n<0) return -1;
if(n==1) return 1;
if(n==2) return 2;
int pre=1;
int res=2;
int t;
for(int i=3;i<=n;i++){
t=res;
res=res+pre;
pre=t;
}
return res;
}
public static void main(String[] args) {
Test solution = new Test();
Long startLong=System.currentTimeMillis();
System.out.println(solution.climbStairs(50000000));
System.out.println("消耗时间:");
System.out.println(System.currentTimeMillis()-startLong);
}
}
输出:
223038178
消耗时间:
57