每日一題,防止癡呆 = =
一、題目大意
假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/climbing-stairs
二、題目思路以及AC代碼
今天的每日一題是兩年前做過的一道題 = =,也是一道比較經典的DP吧,下面我按照官解給出的多個思路的目的,一個個的說一下
思路一:動態規劃
這個肯定是可以用動態規劃求解的。我們令dp[i]表示爬i層臺階共有多少種方法,那麼我們又知道每次只能爬1或2個臺階,那麼dp[i] = dp[i-1] + dp[i-2],直接用DP解決即可,時間複雜度是O(n),然後我們發現其實這個DP只用到了三個數,所以空間複雜度就可以由O(n)優化到O(1)。
思路二:矩陣快速冪
我們發現,由上面提到的矩陣的遞推公式可以得到以下公式:
也就是說,我知道了f(0)和f(1)之後,我們可以通過不斷的乘一個固定的矩陣來得到想要的f(n),那其實就是一個求矩陣冪的問題,關於冪運算,我們是有快速冪的方法可以使得複雜度是O(logn)的,當然矩陣的乘法複雜度是O(1),然後空間複雜度也是O(1)。
思路三:直接用通項公式求解
這就是數學問題了,其實我們觀察遞推公式就可以發現,這個DP數組其實就是一個斐波那契數列,那麼我們就可以直接求通項公式,然後將n帶入求解,但這裏面會涉及到浮點數精度的問題,而且由於通項公式中含有冪次,所以時間複雜度還是O(logn),空間複雜度是O(1)。
AC代碼
這裏只將思路一中的DP寫一下,其實也就是在求斐波那契數列而已。
class Solution {
public:
int climbStairs(int n) {
if (n < 2) return 1;
int first = 1;
int second = 1;
int third;
for (int i=2;i<=n;i++) {
third = first + second;
first = second;
second = third;
}
return third;
}
};
如果有問題,歡迎大家指正!!!