每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是乙個正整數。
示例 1:
輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。
1 階 + 1 階
2 階示例 2:
輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
3. 1 階 + 1 階 + 1 階
4. 1 階 + 2 階
5. 2 階 + 1 階
方法一:暴力遞迴
演算法
第n階可以由以下兩種方法得到:
在第 (n-1)階後向上爬1階。
在第 (n-2)階後向上爬 2 階。
所以到達第 n 階的方法總數就是到第 (n-1)階和第 (n-2) 階的方法數之和。
不難得到遞迴公式:
f(n)=f(n-1)+f(n-2): 觀察發現相當於斐波那契數列(0,1,1,2,3,5,8,…)左移兩個單位。
遞迴實現
public int climbstairs(int n)
複雜度分析
時間複雜度:o(2^n),
樹形遞迴的大小為 2^n 。
空間複雜度:o(n),遞迴樹的深度可以達到 n 。
方法二:記憶化(memoization)遞迴
演算法
在上一種方法中,我們計算每一步的結果時出現了冗餘。另一種思路是,我們可以把每一步的結果儲存在 memo陣列之中,每當函式再次被呼叫,我們就直接從 memo陣列返回結果。
在 memo 陣列的幫助下,我們得到了乙個修復的遞迴樹,其大小減少到 n。
實現在程式的入口處增加對全域性**的查詢,只有**沒有有效結果的時候進行實質性的計算。
public int climbstairs1(int n)
if (memo[n] > 0)
memo[n] = climbstairs(n-1) + climbstairs(n-2);
return memo[n];
}
複雜度分析時間複雜度:o(n),樹形遞迴的大小可以達到 n。
空間複雜度:o(n),遞迴樹的深度可以達到 n。
方法三:動態規劃(dynamic programing)
演算法一般要麼是遞迴要麼是迭代,遞迴:自頂向下遞迴,迭代:自底向上迭代。此方法也是迭代。
遞迴:設計出可行且正確的解。動態規劃:消除重複計算,提高效率。
演算法
不難發現,這個問題可以被分解為一些包含最優子結構的子問題,即它的最優解可以從其子問題的最優解來有效地構建,我們可以使用動態規劃來解決這一問題。
第 i 階可以由以下兩種方法得到:
在第 (i−1) 階後向上爬1階。
在第 (i−2) 階後向上爬 2 階。
所以到達第 i階的方法總數就是到第 (i-1) 階和第 (i-2) 階的方法數之和。
令 dp[i] 表示能到達第 i 階的方法總數:
dp[i]=dp[i-1]+dp[i-2]
實現
public int climbstairs2(int n)
int dp = new int[n+1];
dp[1] = 1;
dp[2] = 2;
for (int i=3; i<=n; i++)
return dp[n];
}
複雜度分析時間複雜度:o(n),單迴圈到 n 。
空間複雜度:o(n),dp陣列用了 n 的空間。
方法四:斐波那契數
演算法
在上述方法中,我們使用 dp 陣列,其中 dp[i]=dp[i-1]+dp[i-2]。可以很容易通過分析得出 dp[i] 其實就是第 i 個斐波那契數。
fib(n)=fib(n-1)+fib(n-2)
現在我們必須找出以 1 和 2 作為第一項和第二項的斐波那契數列中的第 n 個數,也就是說 fib(1)=1 且 fib(2)=2。
public int climbstairs3(int n)
int first = 1;
int second = 2;
for (int i=3; i<=n;i++)
return second;
}
或者
public int climbstairs5(int n)
int f = 0;
int g = 1;
while (1 < n)
return g;
}
複雜度分析
時間複雜度:o(n),單迴圈到 n,需要計算第 n 個斐波那契數。
空間複雜度:o(1),使用常量級空間(3個變數或者兩個)。
附:三步問題。有個小孩正在上樓梯,樓梯有n階台階,小孩一次可以上1階、2階或3階。實現一種方法,計算小孩有多少種上樓梯的方式。結果可能很大,你需要對結果模1000000007。
動態規劃寫法:只要遇到加法就取模,因為兩個太大數相加的話會溢位。
public int waystostep(int n)
if (n <= 2)
int memo = new int[n+1];
memo[0] = 1;
memo[1] = 1;
memo[2] = 2;
for (int i=3;i<=n;i++)
return memo[n];
}
LeetCode 70 爬樓梯 簡單
假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?注意 給定 n 是乙個正整數。示例 1 輸入 2 輸出 2 解釋 有兩種方法可以爬到樓頂。1.1 階 1 階 2.2 階 示例 2 輸入 3 輸出 3 解釋 有三種方法可以爬到樓頂。1...
leetcode 70 爬樓梯 go實現
package main import fmt func main 斐波那契數列 前乙個數等於前兩個數之和 可以想,走到第i級台階有幾種方法呢,2種。1.從i 1級走一步到n級 2.從i 2級走兩步到n級 那也就是說,走到第i級台階的走法有f i f i 1 f i 2 也就是用第i 1級台階的走法...
C 練習 LeetCode 70 爬樓梯
假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?注意 給定 n 是乙個正整數。示例 1 輸入 2 輸出 2 解釋 有兩種方法可以爬到樓頂。1 階 1 階 2 階示例 2 輸入 3 輸出 3 解釋 有三種方法可以爬到樓頂。1 階 1 ...