1. 程式人生 > 其它 >leetcode | 假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?

leetcode | 假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?

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

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

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

示例 1:

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

示例 2:

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

方案1

遞迴呼叫,暴力破解出每一種情況,然後把所有情況累計求和。

public int climbStairs(int n) {
    if( n == 1 ||
n == 0 ) return 1; return climbStairs(n - 1) + climbStairs(n - 2); }

分析

程式碼比較簡潔易懂,但是程式碼本身是用遞迴實現的,所以需要消耗大量的記憶體空間,所以最後的執行結果超時了。

方案2

通過分析示例,我們可以發現它其實就是一個斐波那契數列,讓我們求第n個斐波那契數

public int climbStairs(int n) {
    if(n==1) return 1;
    int a = 1;
    int b = 2;
    int c;
    for(int i=3;i<=
n ;++i){ c = a + b; a = b; b = c; } return b; }

分析

這樣寫只需要一個簡單的迴圈就可以解決問題,程式碼寫起來也比較簡單,而且結果不會超時的,但是這道題是屬於動態規劃的。

方案3

動態規劃解決這個問題。設dp[i]就是i時候的最多方案則

dp[1] = 1;
dp[2] = 2;
dp[3] = dp[2] + dp[1]
......
dp[n] = dp[n-1] + dp[n2]
public int climbStairs(int n) {
    //這裡大小根據自己需要,或者使用 List 也可以
int[] dp = new int[100000]; dp[1] = 1; dp[2] = 2; for( int i = 3;i <= n;++i ){ dp[i] = dp[i-1] + dp[i-2]; } return dp[n]; }

分析

這樣寫就很好的解決這個問題,在動態規劃的世界裡,只要找到遞推公式,那麼答案也就隨之出來了。

其他參考1

演算法 0ms

   public int climbStairs(int n) {
	int numsMax=0;
	int num1=1;
	int num2=2;
        if(n==1){
          return 1;
       }
       if(n==2){
           return 2;
       }
       for(int i=3;i<=n;i++){
         numsMax=num1+num2;
         num1=num2;
         num2=numsMax;
       }
	 return numsMax;
    }

其他參考2

標籤:動態規劃

本問題其實常規解法可以分成多個子問題,爬第n階樓梯的方法數量,等於 2 部分之和
倒數第二步爬上 n-1 階樓梯的方法數量。因為再爬1階就能到第n階
倒數第二步爬上 n-2 階樓梯的方法數量,因為再爬2階就能到第n階
所以我們得到公式

arr[n] = arr[n-1] + arr[n-2]

同時需要初始化

arr[1]=1 和 arr[2]=2

時間複雜度:O(n)

比如爬10級樓梯
則獲取到最後一步是 走1階的方法數量
跟獲取到最後一步是 走2階的方法數量
相加則為 總方法數量

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {
    if (n == 1) {
        return 1;
    }
    if (n == 2) {
        return 2;
    }
    const arr = [];
    arr[1] = 1;
    arr[2] = 2;
    for(let i = 3; i <= n; i++) {
        arr[i] = arr[i - 1] + arr[i - 2];
    }
    return arr[n];
};