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 階來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/climbing-stairs
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
思路分析
1.我們知道當爬一節樓梯的時候只有一種方法,即從0到1,跨一步;
2.爬2階樓梯有兩種方法,從0一次爬到2層,跨兩步;從1一次爬到2層,爬一步;
3.因為我們可選步數為1步或者2步,所以當我們距離終點前1步和前2步的時候,都各只有一種方式到達(差一步跨一步,差兩步跨2步(如果跨1+1,就會和差一步相同))
4.所以我們跨到目標的方法=我們跨到目標前1步的方法+跨到目標前2步的跨法。即f(n)=f(n-1)+f(n-2) (n.> 2)
程式碼編寫:
基於上述思路,可得:
class Solution { public int climbStairs(int n) { return dp(n); } public int dp(int n){ //前兩節臺階比較特殊,單獨列出 if(n==1) return 1; if(n==2) return 2; //定義一個數組,存放前兩階的情況 int[] count=new int[n]; count[0]=1; count[1]=2; //N>2時,按照F(n)=F(n-1)+F(n-2)疊加賦值 for(int i=2;i<n;i++){ count[i]=count[i-1]+count[i-2]; } //因為陣列從0開始,所以返回索引為n-1位 return count[n-1]; } }
提交時間 | 提交結果 | 執行時間 | 記憶體消耗 | 語言 |
---|---|---|---|---|
3 小時前 | 通過 | 0 ms | 35.5 MB |
優化
參考的這個文章,寫的非常清晰明確,毫無基礎也可以看懂呢:https://mp.weixin.qq.com/s/3h9iqU4rdH3EIy5m6AzXsg
儲存時,有太多重複值。
所以根據雜湊表儲存,以時間換空間
class Solution { public int climbStairs(int n) { return dp(n); } public int dp(int n){ if(n==1) return 1; if(n==2) return 2; int[] count=new int[n]; count[0]=1; count[1]=2; // 備忘錄演算法(利用HashMap儲存,) HashMap<Integer,Integer> map =new HashMap<>(); if(map.containsValue(n)){ return map.get(n); } else{ int value=dp(n-1)+dp(n-2); map.put(n,value); return value; } } }
但在leetcode裡,時間超出了,借鑑思路即可(遇到重複值的儲存遍歷時可用雜湊)。
動態規劃
class Solution {
public int climbStairs(int n) {
return dp(n);
}
public int dp(int n){
if(n==1) return 1;
if(n==2) return 2;
// 動態規劃
int a=1;
int b=2;
int temp=0;
for(int i=2;i<n;i++){
temp=a+b;
a=b;
b=temp;
}
return temp;
}
}
利用三個變數互相迭代更新,反正最終我們需要知道f(n)=f(n-1)+f(n-2) (n.> 2) ,也就是說,我們最後只要保留f(n),f(n-1),f(n-2) ,前面的值迭代替換掉,對我們輸出最終結果沒有影響。
同時,我們空間中只申請了3個變數a,b,temp,空間複雜度是O(1),時間上需要對取決於n的值,為o(n)。
提交時間 | 提交結果 | 執行時間 | 記憶體消耗 | 語言 |
---|---|---|---|---|
幾秒前 | 通過 | 0 ms | 35.2 MB |