LeetCode Algorithm 70. 爬楼梯
Title
假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。
示例 1:
輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。
示例 2:
輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
Solve
遞歸
遞歸的思路就比較簡單了,但是一般第一個能想到的方法都會超時。
def climbStairs_recursion(self, n: int) -> int:def solve(num):if num == 0:return 1if num < 0:return 0return solve(num - 1) + solve(num - 2)return solve(n)
動態規劃
用f(x)表示爬到第x級臺階的方案數,考慮最后一步可能跨了一級臺階,也可能跨了兩級臺階,可以列出如下式子:f(x)=f(x?1)+f(x?2)f(x)=f(x-1)+f(x-2)f(x)=f(x?1)+f(x?2)這就是動態規劃的轉移方程,它意味著爬到第x級臺階的方案數是爬到第x-1級和爬到第x-2級臺階方案數的總和。
下面我們來討論邊界條件,從第0級開始:f(0)=1,從第0級到第1級只有一種解決方案,即爬1級,所以f(1)=1,以這兩個作為邊界條件就可以繼續往后推導出第n級的解決方案。
我們不妨寫幾項來驗證一下,根據轉移方程得到 f(2) = 2,f(3) = 3,f(4) = 5…我們把這些情況都枚舉出來,發現計算的結果是正確的。
通過轉移方程和邊界條件給出一個時間復雜度和空間復雜度都是 O(n) 的實現,但是由于這里的 f(x) 只和 f(x - 1) 與 f(x - 2) 有關,所以我們可以用「滾動數組思想」把空間復雜度優化成 O(1)。
def climbStairs_dynamic_programming(self, n: int) -> int:f0, f1, ans = 0, 0, 1for i in range(1, n + 1):f0 = f1f1 = ansans = f0 + f1return ans復雜度分析
時間復雜度:循環執行 n 次,每次花費常數的時間代價,故漸進時間復雜度為 O(n)。
空間復雜度:這里只用了常數個變量作為輔助空間,故漸進空間復雜度為 O(1)。
矩陣快速冪
動態規劃方法的時間復雜度為O(n),只適用于n比較小的情況,在n變大之后,O(n)的時間復雜度會讓這個算法看起來有些捉襟見肘,我們可以用「矩陣快速冪」的方法來優化這個過程。
首先我們可以構建這樣一個遞推關系:[1110][f(n)f(n?1)]=[f(n)+f(n?1)f(n)]=[f(n+1)f(n)]\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix} =\begin{bmatrix} f(n)+ f(n-1) \\ f(n) \end{bmatrix} =\begin{bmatrix} f(n+1) \\ f(n) \end{bmatrix}[11?10?][f(n)f(n?1)?]=[f(n)+f(n?1)f(n)?]=[f(n+1)f(n)?]
因此:[f(n+1)f(n)]=[1110][f(n)f(n?1)]=[1110]2[f(n?1)f(n?2)]=...=[1110]n[f(1)f(0)]\begin{bmatrix} f(n+1) \\ f(n) \end{bmatrix}= {\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}} \begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix}={\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}}^2 \begin{bmatrix} f(n-1) \\ f(n-2) \end{bmatrix}=...={\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}}^n \begin{bmatrix} f(1) \\ f(0) \end{bmatrix}[f(n+1)f(n)?]=[11?10?][f(n)f(n?1)?]=[11?10?]2[f(n?1)f(n?2)?]=...=[11?10?]n[f(1)f(0)?]
令:M=[1110]M= \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} M=[11?10?]因此,我們只要快速計算矩陣M的n次冪,就可以得到f(n)得值。
def climbStairs_matrix_fast_power(self, n: int) -> int:def multiply(matrixA, matrixB):ans = []for i in range(2):ans.append([])for j in range(2):ans[i].append(matrixA[i][0] * matrixB[0][j] + matrixA[i][1] * matrixB[1][j])return ansdef solve(matrix, num):ret = [[1, 0], [0, 1]]while num > 0:if (num & 1) == 1:ret = multiply(ret, matrix)num >>= 1matrix = multiply(matrix, matrix)return retM = [[1, 1], [1, 0]]res = solve(M, n)return res[0][0]復雜度分析
時間復雜度:同快速冪,O(log n)。
空間復雜度:O(1)。
總結
以上是生活随笔為你收集整理的LeetCode Algorithm 70. 爬楼梯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux操作系统中Anaconda的安
- 下一篇: 如何将CSV数据存储到Hive