[算法專欄] 爬樓梯問題


  題目:

  一個台階總共有n 級,如果一次可以跳1 級,也可以跳2 級,求總共有多少種跳法。

  備注:

  這個題目經常出現,包括Microsoft 等比較重視算法的公司都曾先后選用過個這道題作為面試題或者筆試題。

  問題分析:

  如果只有1 級台階,那顯然只有一種跳法;

  如果有2 級台階,那就有兩種跳的方法了:一種是分兩次跳,每次跳1 級;另外一種就是一次跳2 級。

  當台階數>2 級時,第一次跳的時候就有兩種不同的選擇:一種是 第一次只跳1 級,此時跳法數目等於后面剩下的n-1 級台階的跳法數目,即為f(n-1);另外一種選擇是第一次跳2 級,此時跳法數目等於后面剩下的n-2 級台階的跳法數目,即為f(n-2)。 所以,n 級台階時的不同跳法的總數 f(n) = f(n-1) + f(n-2)。

           /  1       (n=1)
  即:f(n) =  2         (n=2)
           \  f(n-1) + (f-2)   (n>2)

  其實,這就是Fibonacci 序列。算法復雜度為:(O(n))。 

  偽代碼如下:

int Fibonacci1(unsigned int N)  

{  

    if(N<=2)  

        return N;  

    int fibtwo=2;  

    int fibone=1;  

    int fibN=0;  

    for(unsigned int i=3;i<=N;i++)  

    {  

        fibN=fibone+fibtwo;  

        fibone=fibtwo;  

        fibtwo=fibN;  

    }  

    return fibN;  

}  

  具體實現如下(6種實現):

  1 /**
  2  * 爬樓梯問題: 實質就是斐波那契數列.
  3  * 
  4  * @author X-knight
  5  *
  6  */
  7 public class ClimbTheStairs {
  8     int total;
  9 
 10     // 遞歸調用
 11     public int fib01(int n) {
 12         if (n == 1 || n == 2)
 13             total = n;
 14         else
 15             total = fib01(n - 2) + fib01(n - 1);
 16         return total;
 17     }
 18 
 19     // 三目運算符
 20     public int fib02(int n) {
 21         return (n == 1 || n == 2) ? n : fib02(n - 2) + fib02(n - 1);
 22     }
 23 
 24     // 備忘錄法
 25     public int dfs(int n, int[] array) {
 26         if (array[n] != 0) {
 27             return array[n];
 28         } else {
 29             array[n] = dfs(n - 1, array) + dfs(n - 2, array);
 30             return array[n];
 31         }
 32     }
 33 
 34     public int fib03(int n) {
 35         if (n == 0) {
 36             return 1;
 37         }
 38         if (n == 1 || n == 2) {
 39             return n;
 40         } else {
 41             int[] array = new int[n + 1];
 42             array[1] = 1;
 43             array[2] = 2;
 44             return dfs(n, array);
 45         }
 46     }
 47 
 48     // 動態規划法 (利用數組來存儲)
 49     public int fib04(int n) {
 50         if (n == 0)
 51             return 1;
 52         int[] array = new int[n + 1];
 53         array[0] = 1;
 54         array[1] = 1;
 55         for (int i = 2; i <= n; i++) {
 56             array[i] = array[i - 1] + array[i - 2];
 57         }
 58         return array[n];
 59     }
 60 
 61     // 狀態壓縮法(又稱滾動數組、滑動窗口,用於優化動態規划法的空間復雜度)
 62     public int fib05(int n) {
 63         if (n == 1 || n == 0)
 64             return 1;
 65         n = n - 1;
 66         int result = 0;
 67         int zero = 1;
 68         int first = 1;
 69         while (n > 0) {
 70             result = zero + first;
 71             zero = first;
 72             first = result;
 73             n--;
 74         }
 75         return result;
 76     }
 77 
 78     // 斐波那契數列的通項公式
 79     public int fib06(int n) {
 80         if (n == 0)
 81             return 1;
 82         if (n == 1 || n == 2)
 83             return n;
 84         int result = (int) Math.floor(
 85                 1 / Math.sqrt(5) * (Math.pow((1 + Math.sqrt(5)) / 2, n + 1) - Math.pow((1 - Math.sqrt(5)) / 2, n + 1)));
 86         return result;
 87     }
 88 
 89     @Test
 90     public void testClimb() {
 91         int num01 = fib01(7);
 92         System.out.println(num01);
 93         int num02 = fib02(8);
 94         System.out.println(num02);
 95         int num03 = fib03(0);
 96         System.out.println(num03);
 97         int num04 = fib04(8);
 98         System.out.println(num04);
 99         int num05 = fib05(8);
100         System.out.println(num05);
101         int num06 = fib06(2);
102         System.out.println(num06);
103     }
104 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM