手撕LeetCode—70 爬樓梯

假設你正在爬樓梯。需要 n 步你才能到達樓頂。

每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?

注意:給定 n 是一個正整數。

示例 1:

輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。
1.  1 步 + 1 步
2.  2 步

示例 2:

輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
1.  1 步 + 1 步 + 1 步
2.  1 步 + 2 步
3.  2 步 + 1 步

這是一個很經典的問題了,記得高中的數學課上就講過這個問題。這個問題如果按照正常的邏輯來思考,從第一層爬到頂有多少種方式,那就太複雜了,不符合我們算法求解的要求。

既然從第一層向上推導太複雜,那我們可以換一個思路:那就是從頂層往回退。假如我們要爬n層樓梯,還剩一層就到頂了,那麼我們再向上走一步就能到頂,如果設爬上n-1層樓梯的方式有f(n-1)種,那麼在這種情況下,我們爬上第n層也有f(n-1)種方式。

但是,還沒有結束,因爲最後一步可以爬1層也可以爬2層,那麼我們爬上最後一層可以是從n-2層一次爬了2層到第n層。這種情況下,爬n層樓梯又有了f(n-2)中方式。

由於每次只能上1層或者2層樓梯,所以到達第n層的最後一步就只能是從n-1層爬1層,從n-2層爬兩層。那麼爬上n層樓梯的總方式就爲f(n)=f(n-1)+f(n-2)。有沒有很熟悉這個公式啊,對,這就是著名的斐波那契數列啊大笑

既然是熟悉的斐波那契數列,那就不多說了吧,直接上代碼:

public int climbStairs(int n) {

    if (n == 0) {
        return 0;
    }

    if (n == 1) {
        return 1;
    }

    if (n == 2) {
        return 2;
    }

    return climbStairs(n - 1) + climbStairs(n - 2);

}

這是最簡單的斐波那契數列的寫法,使用了遞歸,但是這種寫法的時間複雜度太大。

提交結果:

於是又經過思考,耗時太長的原因是使用了遞歸,能不能不用遞歸來實現呢?

public int climbStairs(int n) {

    if (n <= 1) {
        return 1;
    }
    
    int res = 0;
    int n1 = 1;
    int n2 = 1;
    for (int i = 2; i <= n; ++i) {
        res = n2 + n1;
        n1 = n2;
        n2 = res;
    }
    return res;
}

這次改進之後好多了得意




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章