領扣-70 爬樓梯 Climbing Stairs MD
Markdown版本筆記 | 我的GitHub首頁 | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | [email protected] |
領扣-70 爬樓梯 Climbing Stairs MD
目錄
目錄爬樓梯 Climbing Stairs
題目
遞歸方式
動態規劃
優化
爬樓梯 Climbing Stairs
題目
假設你正在爬樓梯。需要 n 階你才能到達樓頂。
You are climbing a stair case. It takes n steps to reach to the top.
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
註意:給定 n 是一個正整數。
Note: Given n will be a positive integer.
示例 1:
輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。
1. 1 階 + 1 階
2. 2 階
示例 2:
輸入: 3 輸出: 3 解釋: 有三種方法可以爬到樓頂。 1. 1 階 + 1 階 + 1 階 2. 1 階 + 2 階 3. 2 階 + 1 階
遞歸方式
這個題目跟斐波那契數列非常相似,假設梯子有n層,那麽如何爬到第n層呢?
因為每次只能爬1或2步,那麽爬到第n層的方法要麽是從第 n-1
層一步上來的,要不就是從 n-2
層2步上來的,所以遞推公式非常容易的就得出了:dp[n] = dp[n-1] + dp[n-2]
class Solution { public int climbStairs(int n) { if (n == 1) return 1; if (n == 2) return 2; return climbStairs(n - 1) + climbStairs(n - 2); } }
這樣的代碼思路很清晰,在我們的編譯器上,也會輕松通過,但是提交到leetcode往往會提示超出時間限制,是因為在n大的時候,遞歸棧非常之深,每次去遞歸時間開銷很大,所以會拋出超時。
那麽怎麽去在這個思路上去改進呢?
有的同學可能會發現,在遞歸的時候,不斷有重復的遞歸,比如10會有9和8 9會有8和7 這時8已經出現了兩次,而下面更小的數字會有更多的重復,那麽我們把這些數據存儲下來,方便調用不是可以節省開銷?
class Solution {
private int[] memo;
public int climbStairs(int n) {
memo = new int[n + 1];
Arrays.fill(memo, -1);
return getClimbStairs(n);
}
private int getClimbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
if (memo[n] == -1) memo[n] = getClimbStairs(n - 1) + getClimbStairs(n - 2);
return memo[n];
}
}
我們只需要聲明一個 memo 數組,把遞歸中間過程的值存儲下來就好,可以大大的提高效率,這時候提交給 leetcode 已經可以獲得AC了
動態規劃
class Solution {
public int climbStairs(int n) {
int[] memo = new int[n + 1];
memo[0] = 1;
memo[1] = 2;
for (int i = 2; i <= n; i++) {
memo[i] = memo[i - 1] + memo[i - 2];
}
return memo[n - 1];
}
}
優化
我們可以對空間進行優化,我們只用幾個整型變量來存儲過程值,來模擬上面累加的過程,而不用存儲所有的值,參見代碼如下:
class Solution {
public int climbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
int a1 = 1, a2 = 2, a3 = 0;
while (n-- > 2) {
a3 = a1 + a2;
a1 = a2;
a2 = a3;
}
return a3;
}
}
上述邏輯可以優化為:
class Solution {
public int climbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
int a = 1, b = 2;
while (n-- >= 2) {
b += a; //相加的值
a = b - a; //原來的 b
}
return a + b;
}
}
或者這樣:
class Solution {
public int climbStairs(int n) {
int a = 1, b = 1;
while (n-- > 0) {
b += a; //相加的值
a = b - a; //原來的 b
}
return a;
}
}
2018-12-7
領扣-70 爬樓梯 Climbing Stairs MD