題目
來源:力扣(LeetCode)
鏈接:爬樓梯
思路一 暴力搜索
暴力搜索,題目可以轉換爲整數n可以拆成a個1和b個2相加 這種拆法有多少種 ,且和是不同的拆法。
由於每踏一步有兩種選法,至少需要篩選n次,所以時間複雜度約爲o(2n)但這種做法會超時。
代碼
void dfs(int sum,int n,int *cnt){
if(sum==n){
(*cnt)++;
return;
}
if(sum>n){
return;
}
for(int i=1;i<=2;i++){
dfs(sum+i,n,cnt);
}
}
int climbStairs(int n){
int cnt=0;
dfs(0,n,&cnt);
return cnt;
}
思路二 轉換爲斐波那契數
爬到第n層的有幾張走法可以等價於爬到n-1層的走法加爬到n-2的走法。
即符合斐波那契數的特點。
求斐波那契數可以用以下方法
- 遞歸法優化,使用一維數組暫存中間結果
- 動態規劃求斐波那契數
遞歸法優化
如下圖,以n=5爲例,在計算f(5)時f(3)已經計算過,不需重複計算,返回數組元素fib[3]即可
代碼
int Fib(int i,int* fib){
if(i==0||i==1){
return 1;
}
if(fib[i]>0){
return fib[i];
}
fib[i]=Fib(i-1,fib)+Fib(i-2,fib);
return fib[i];
}
int climbStairs(int n){
int fib[10000000];
fib[0]=1;fib[1]=1;
return Fib(n,fib);
}
動態規劃
初始狀態爲
動態轉移方程爲
代碼
int climbStairs(int n){
int *dp=(int*)malloc(sizeof(int)*(n+1));
dp[0]=1;
dp[1]=1;
for(int i=2;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
int res=dp[n];
free(dp);
return res;
}