Leetcode C++ 70. Climbing Stairs 【斐波拉契數列】

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?

Note: Given n will be a positive integer.

  • Example 1:
    Input: 2
    Output: 2
    Explanation: There are two ways to climb to the top.
    1. 1 step + 1 step
    2. 2 steps
    
  • Example 2:
    Input: 3
    Output: 3
    Explanation: There are three ways to climb to the top.
    1. 1 step + 1 step + 1 step
    2. 1 step + 2 steps
    3. 2 steps + 1 step
    

題意:爬樓梯,每次走1步或者2步,走上n階的樓梯,有多少種走法。

  1. 方法一:暴力。O(2n)的時間複雜度,n=44過不去。
    class Solution {
    public:
        int stairs[50] = {0, 1, 2};
        int climbStairs(int n) {
            if (n <= 2) return n;
            else return climbStairs(n - 1) + climbStairs(n - 2); 
        }
    };
    

在這裏插入圖片描述

  1. 方法二:記憶化搜索。memorization。因爲法一存在很多重複計算,導致時間太長,因此把一些已經求出來的解存進數組,不重複求解。時間空間都是O(n)。

    執行用時 :0 ms, 在所有 C++ 提交中擊敗了100.00% 的用戶
    內存消耗 :8.3 MB, 在所有 C++ 提交中擊敗了62.09%的用戶

    class Solution {
    public:
        int stairs[50] = {0, 1, 2};
        int climbStairs(int n) {
            if (n <= 2) return n;
            else {
                if (stairs[n - 1] == 0) stairs[n - 1] = climbStairs(n - 1);
                if (stairs[n - 2] == 0) stairs[n - 2] = climbStairs(n - 2);
                return stairs[n - 1] + stairs[n - 2];
            } 
        }
    };
    
  2. 方法三:動態規劃。這個問題可以被分解爲一些包含最優子結構的子問題,即它的最優解可以從其子問題的最優解來有效地構建。第 i 階可以由以下兩種方法得到:

     在第 (i−1) 階後向上爬 1 階。 
     在第 (i−2) 階後向上爬 2 階。
    

    所以到達第 i 階的方法總數就是到第 (i−1) 階和第 (i-2) 階的方法數之和。令 dp[i] 表示能到達第 iii 階的方法總數:dp[i]=dp[i−1]+dp[i−2]。時間空間複雜度均爲O(n)。

    執行用時 :4 ms, 在所有 C++ 提交中擊敗了62.73% 的用戶
    內存消耗 :8.4 MB, 在所有 C++ 提交中擊敗了54.70%的用戶

    class Solution {
    public:
        int climbStairs(int n) {
            if (n <= 2) return n;
            int *dp = new int[n + 1];
            dp[1] = 1;
            dp[2] = 2;
            for (int i = 3; i <= n; i++) {
                dp[i] = dp[i - 1] + dp[i - 2];
            }
            return dp[n];
        }
    };
    
  3. 方法四:斐波那契數列遞推。這個題實際上就是斐波拉契數列。只需使用兩個變量即可推出答案要求的解。時間O(n),空間O(1)。 Fib(n)=Fib(n−1)+Fib(n−2)

    現在我們必須找出以 1 和 2 作爲第一項和第二項的斐波那契數列中的第 n 個數,也就是說 Fib(1)=1 且 Fib(2)=2。

    執行用時 :0 ms, 在所有 C++ 提交中擊敗了100.00% 的用戶
    內存消耗 :8.3 MB, 在所有 C++ 提交中擊敗了70.59%的用戶

    class Solution {
    public:
        int climbStairs(int n) {
            if (n <= 2) return n;
            int first = 1, second = 2;
            for (int i = 3; i <= n; i++) {
                int third = first + second;
                first = second;
                second = third;
            }
            return second;
        }
    };
    
  4. 方法五:斐波拉契數列求解公式:
    在這裏插入圖片描述Fn=1/5[(1+52)n(152)n]F_n = 1/\sqrt{5}\left[ \left(\frac{1+\sqrt{5}}{2}\right)^{n} - \left(\frac{1-\sqrt{5}}{2}\right)^{n} \right]
    Fn=1/5((1+52)n+1(152)n+1)F_n = 1/\sqrt{5}\left( \left(\frac{1+\sqrt{5}}{2}\right)^{n+1} - \left(\frac{1-\sqrt{5}}{2}\right)^{n+1} \right)
    時間複雜度爲O(log(n)),用在快速冪上面了,空間O(1)。
    執行用時 :4 ms, 在所有 C++ 提交中擊敗了62.73% 的用戶
    內存消耗 :8.5 MB, 在所有 C++ 提交中擊敗了32.17%的用戶

    class Solution {
    public:
        int climbStairs(int n) {
            double sqrt5 = sqrt(5.0);
            double fibn = pow((1 + sqrt5) / 2, n + 1) - pow((1 - sqrt5) / 2, n + 1);
            return (int)(fibn / sqrt5);
        }
    };
    
  5. 方法六:Binets方法 :使用矩陣相乘。
    solutions裏面分享的方法。

發佈了166 篇原創文章 · 獲贊 59 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章