1、題目描述
假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。
來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/climbing-stairs 著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
2、示例
示例1:
輸入: 2 輸出: 2 解釋: 有兩種方法可以爬到樓頂。 1. 1 階 + 1 階 2. 2 階
示例2:
輸入: 3 輸出: 3 解釋: 有三種方法可以爬到樓頂。 1. 1 階 + 1 階 + 1 階 2. 1 階 + 2 階 3. 2 階 + 1 階
3、解題思路
第一次看到這道題,可能會有點不知所措。但是不要着急,我們可以暴力,我們可以窮舉!
思路1:
當 n = 1時,一共跳 1 級;
當 n = 2時,一共跳 2 級;
當 n = 3時,一共跳 3 級;
當 n = 4時,一共跳 5 級;
當 n = 5時,一共跳 8 級;
...
咦?這不就是去了第一個項的斐波那契數列嘛?
到此為止,我們可以列出方程了:f(n) = f(n-1) + f(n-2);
不過,我們需要手動增加 0 項為 1 。
所以,代碼如下:
class Solution { public int climbStairs(int n) { if(n==1 || n==0){ return 1; } return climbStairs(n-1)+climbStairs(n-2); } }
提交結果:
思路2:
第二個思路是,利用動態規划。其實,這個題目也是動態規划的經典題目。
本問題其實常規解法可以分成多個子問題,爬第n階樓梯的方法數量,等於以下兩部分之和:
- 爬上 n-1 階樓梯的方法數量:因為再爬1階就能到第 n 階;
- 爬上 n-2 階樓梯的方法數量:因為再爬2階就能到第 n 階。
所以我們得到公式 dp[n] = dp[n-1] + dp[n-2];
同時需要初始化 dp[0]=1 和 dp[1]=1;
時間復雜度:O(n)。
代碼如下:
class Solution { public int climbStairs(int n) { if(n==1 || n==0){ return 1; } int[] arr = new int[n+1]; arr[0] = 1; arr[1] = 1; for(int i = 2; i<n+1; i++){ arr[i] = arr[i-1] + arr[i-2]; } return arr[n]; } }
提交結果如下:
思路3:
是的,這道題還有第三種方法。
那就是純數學方法,有人說上面不也是數學方法嘛?是的,上面也是,但是下面這個更厲害。
由第一種方法我們可知是斐波那契數列,其實菲波那切數列是有公式的。
時間復雜度為:O(log n)。
代碼如下:
class Solution { public int climbStairs(int n) { double sqrt_5 = Math.sqrt(5); double fib_n = Math.pow((1 + sqrt_5) / 2, n + 1) - Math.pow((1 - sqrt_5) / 2,n + 1); return (int)(fib_n / sqrt_5); } }
提交結果和第二種差不多。
OK ,下一篇我們來看跳台階的進階版。
Over......