爬樓梯問題有多種出現形式,有不固定最多可跨階數(即最多可跨階數爲M,M作爲方法參數)的,有固定每次最多可跨2階的。接下來,我就對以上兩種出線形勢分別進行分析。
(一)固定每次最多跨越2階,使用非遞歸方式實現:
1、問題描述:
假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。
2、首先我們把 n<=5 的不同情況列出來:
1 | 2 | 3 | 4 | 5 |
1 | 2 | 3 | 5 | 8 |
綜上我們可以看出,爬樓梯的方案數f(n) = f(n) + f(n-1)
3、我們用java代碼實現以上思路:
class Solution {
public int climbStairs(int n) {
if(n==1||n==2){
return n;
}
int f1 = 1;
int f2 = 2;
int temp;
for(int i=3; i<=n; i++){
temp = f2;
f2 += f1;
f1 = temp;
}
return f2;
}
}
4、運行結果:
(二)使用遞歸方式實現
1、問題描述:
假設一個樓梯有 N 階臺階,人每次最多可以跨 M 階,求總共的爬樓梯方案數。
2、算法實現(java語言):
private static int calculateCount(int ladder, int maxJump) {
int jump = 0;
if (ladder == 0) {
return 1;
}
if (ladder >= maxJump) {
// 剩下的樓梯大於最大可跳躍數
for (int i = 1; i <= maxJump; i++) {
jump += calculateCount(ladder - i, maxJump);
}
} else {
// 剩下的樓梯不足最大可跳躍數
jump = calculateCount(ladder, ladder);
}
return jump;
}
(三)遞歸和非遞歸實現性能比較:
package test;
/**
*
* @author FHY
* 爬樓梯問題
*
*/
public class DynamicTest {
public static void main(String[] args) {
//對遞歸和非遞歸實現兩種方法進行性能比較:
long start = System.currentTimeMillis();
getNums(30);
long end1 = System.currentTimeMillis();
System.out.println("非遞歸實現:"+(end1-start));
calculateCount(30,2);
long end2 = System.currentTimeMillis();
System.out.println("遞歸實現:"+(end2-end1));
}
private static int calculateCount(int ladder, int maxJump) {
int jump = 0;
if (ladder == 0) {
return 1;
}
if (ladder >= maxJump) {
// 剩下的樓梯大於最大可跳躍數
for (int i = 1; i <= maxJump; i++) {
jump += calculateCount(ladder - i, maxJump);
}
} else {
// 剩下的樓梯不足最大可跳躍數
jump = calculateCount(ladder, ladder);
}
return jump;
}
public static int getNums(int n){
if(n==1||n==2){
return n;
}
int f1 = 1;
int f2 = 2;
int temp;
for(int i=3; i<=n; i++){
temp = f2;
f2 += f1;
f1 = temp;
}
long end = System.currentTimeMillis();
return f2;
}
}
輸出:
非遞歸實現:0
遞歸實現:14
可見,遞歸實現性能很差!