60
60
61
61
时间复杂度 $O(n)$,空间复杂度 $O(1)$。
62
62
63
+ ** 方法二:矩阵快速幂**
64
+
65
+ 我们设 $Fib(n)$ 表示一个 $1 \times 2$ 的矩阵 $\begin{bmatrix} F_n & F_ {n - 1} \end{bmatrix}$,其中 $F_n$ 和 $F_ {n - 1}$ 分别是第 $n$ 个和第 $n - 1$ 个斐波那契数。
66
+
67
+ 我们希望根据 $Fib(n-1) = \begin{bmatrix} F_ {n - 1} & F_ {n - 2} \end{bmatrix}$ 推出 $Fib(n)$。也即是说,我们需要一个矩阵 $base$,使得 $Fib(n - 1) \times base = Fib(n)$,即:
68
+
69
+ $$
70
+ \begin{bmatrix}
71
+ F_{n - 1} & F_{n - 2}
72
+ \end{bmatrix} \times base = \begin{bmatrix} F_n & F_{n - 1} \end{bmatrix}
73
+ $$
74
+
75
+ 由于 $F_n = F_ {n - 1} + F_ {n - 2}$,所以矩阵 $base$ 的第一列为:
76
+
77
+ $$
78
+ \begin{bmatrix}
79
+ 1 \\
80
+ 1
81
+ \end{bmatrix}
82
+ $$
83
+
84
+ 第二列为:
85
+
86
+ $$
87
+ \begin{bmatrix}
88
+ 1 \\
89
+ 0
90
+ \end{bmatrix}
91
+ $$
92
+
93
+ 因此有:
94
+
95
+ $$
96
+ \begin{bmatrix} F_{n - 1} & F_{n - 2} \end{bmatrix} \times \begin{bmatrix}1 & 1 \\ 1 & 0\end{bmatrix} = \begin{bmatrix} F_n & F_{n - 1} \end{bmatrix}
97
+ $$
98
+
99
+ 我们定义初始矩阵 $res = \begin{bmatrix} 1 & 1 \end{bmatrix}$,那么 $F_n$ 等于 $res$ 乘以 $base^{n - 1}$ 的结果矩阵中第一行的第一个元素。使用矩阵快速幂求解即可。
100
+
101
+ 时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。
102
+
63
103
<!-- tabs:start -->
64
104
65
105
### ** Python3**
@@ -75,6 +115,31 @@ class Solution:
75
115
return b
76
116
```
77
117
118
+ ``` python
119
+ class Solution :
120
+ def climbStairs (self , n : int ) -> int :
121
+ def mul (a : List[List[int ]], b : List[List[int ]]) -> List[List[int ]]:
122
+ m, n = len (a), len (b[0 ])
123
+ c = [[0 ] * n for _ in range (m)]
124
+ for i in range (m):
125
+ for j in range (n):
126
+ for k in range (len (a[0 ])):
127
+ c[i][j] = c[i][j] + a[i][k] * b[k][j]
128
+ return c
129
+
130
+ def pow (a : List[List[int ]], n : int ) -> List[List[int ]]:
131
+ res = [[1 , 1 ], [0 , 0 ]]
132
+ while n:
133
+ if n & 1 :
134
+ res = mul(res, a)
135
+ n >>= 1
136
+ a = mul(a, a)
137
+ return res
138
+
139
+ a = [[1 , 1 ], [1 , 0 ]]
140
+ return pow (a, n - 1 )[0 ][0 ]
141
+ ```
142
+
78
143
### ** Java**
79
144
80
145
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -93,6 +158,40 @@ class Solution {
93
158
}
94
159
```
95
160
161
+ ``` java
162
+ class Solution {
163
+ public int climbStairs (int n ) {
164
+ int [][] a = {{1 , 1 ,}, {1 , 0 }};
165
+ return pow(a, n - 1 )[0 ][0 ];
166
+ }
167
+
168
+ private int [][] mul (int [][] a , int [][] b ) {
169
+ int m = a. length, n = b[0 ]. length;
170
+ int [][] c = new int [m][n];
171
+ for (int i = 0 ; i < m; ++ i) {
172
+ for (int j = 0 ; j < n; ++ j) {
173
+ for (int k = 0 ; k < a[0 ]. length; ++ k) {
174
+ c[i][j] += a[i][k] * b[k][j];
175
+ }
176
+ }
177
+ }
178
+ return c;
179
+ }
180
+
181
+ private int [][] pow (int [][] a , int n ) {
182
+ int [][] res = {{1 , 1 }, {0 , 0 }};
183
+ while (n > 0 ) {
184
+ if ((n & 1 ) == 1 ) {
185
+ res = mul(res, a);
186
+ }
187
+ n >> = 1 ;
188
+ a = mul(a, a);
189
+ }
190
+ return res;
191
+ }
192
+ }
193
+ ```
194
+
96
195
### ** C++**
97
196
98
197
``` cpp
@@ -110,6 +209,87 @@ public:
110
209
};
111
210
```
112
211
212
+ ```cpp
213
+ class Solution {
214
+ public:
215
+ int climbStairs(int n) {
216
+ vector<vector<long long>> a = {{1, 1}, {1, 0}};
217
+ return pow(a, n - 1)[0][0];
218
+ }
219
+
220
+ private:
221
+ vector<vector<long long>> mul(vector<vector<long long>>& a, vector<vector<long long>>& b) {
222
+ int m = a.size(), n = b[0].size();
223
+ vector<vector<long long>> res(m, vector<long long>(n));
224
+ for (int i = 0; i < m; ++i) {
225
+ for (int j = 0; j < n; ++j) {
226
+ for (int k = 0; k < a[0].size(); ++k) {
227
+ res[i][j] += a[i][k] * b[k][j];
228
+ }
229
+ }
230
+ }
231
+ return res;
232
+ }
233
+
234
+ vector<vector<long long>> pow(vector<vector<long long>>& a, int n) {
235
+ vector<vector<long long>> res = {{1, 1}, {0, 0}};
236
+ while (n) {
237
+ if (n & 1) {
238
+ res = mul(res, a);
239
+ }
240
+ a = mul(a, a);
241
+ n >>= 1;
242
+ }
243
+ return res;
244
+ }
245
+ };
246
+ ```
247
+
248
+ ### ** Go**
249
+
250
+ ``` go
251
+ func climbStairs (n int ) int {
252
+ a , b := 0 , 1
253
+ for i := 0 ; i < n; i++ {
254
+ a, b = b, a+b
255
+ }
256
+ return b
257
+ }
258
+ ```
259
+
260
+ ``` go
261
+ type matrix [2 ][2 ]int
262
+
263
+ func climbStairs (n int ) int {
264
+ a := matrix{{1 , 1 }, {1 , 0 }}
265
+ return pow (a, n-1 )[0 ][0 ]
266
+ }
267
+
268
+ func mul (a , b matrix ) (c matrix ) {
269
+ m , n := len (a), len (b[0 ])
270
+ for i := 0 ; i < m; i++ {
271
+ for j := 0 ; j < n; j++ {
272
+ for k := 0 ; k < len (a[0 ]); k++ {
273
+ c[i][j] += a[i][k] * b[k][j]
274
+ }
275
+ }
276
+ }
277
+ return
278
+ }
279
+
280
+ func pow (a matrix , n int ) matrix {
281
+ res := matrix{{1 , 1 }, {0 , 0 }}
282
+ for n > 0 {
283
+ if n&1 == 1 {
284
+ res = mul (res, a)
285
+ }
286
+ a = mul (a, a)
287
+ n >>= 1
288
+ }
289
+ return res
290
+ }
291
+ ```
292
+
113
293
### ** JavaScript**
114
294
115
295
``` js
@@ -129,15 +309,47 @@ var climbStairs = function (n) {
129
309
};
130
310
```
131
311
132
- ### ** Go**
312
+ ``` js
313
+ /**
314
+ * @param {number} n
315
+ * @return {number}
316
+ */
317
+ var climbStairs = function (n ) {
318
+ const a = [
319
+ [1 , 1 ],
320
+ [1 , 0 ],
321
+ ];
322
+ return pow (a, n - 1 )[0 ][0 ];
323
+ };
133
324
134
- ``` go
135
- func climbStairs (n int ) int {
136
- a , b := 0 , 1
137
- for i := 0 ; i < n; i++ {
138
- a, b = b, a+b
139
- }
140
- return b
325
+ function mul (a , b ) {
326
+ const [m , n ] = [a .length , b[0 ].length ];
327
+ const c = Array (m)
328
+ .fill (0 )
329
+ .map (() => Array (n).fill (0 ));
330
+ for (let i = 0 ; i < m; ++ i) {
331
+ for (let j = 0 ; j < n; ++ j) {
332
+ for (let k = 0 ; k < a[0 ].length ; ++ k) {
333
+ c[i][j] += a[i][k] * b[k][j];
334
+ }
335
+ }
336
+ }
337
+ return c;
338
+ }
339
+
340
+ function pow (a , n ) {
341
+ let res = [
342
+ [1 , 1 ],
343
+ [0 , 0 ],
344
+ ];
345
+ while (n) {
346
+ if (n & 1 ) {
347
+ res = mul (res, a);
348
+ }
349
+ a = mul (a, a);
350
+ n >>= 1 ;
351
+ }
352
+ return res;
141
353
}
142
354
```
143
355
@@ -154,6 +366,46 @@ function climbStairs(n: number): number {
154
366
}
155
367
```
156
368
369
+ ``` ts
370
+ function climbStairs(n : number ): number {
371
+ const a = [
372
+ [1 , 1 ],
373
+ [1 , 0 ],
374
+ ];
375
+ return pow (a , n - 1 )[0 ][0 ];
376
+ }
377
+
378
+ function mul(a : number [][], b : number [][]): number [][] {
379
+ const [m, n] = [a .length , b [0 ].length ];
380
+ const c = Array (m )
381
+ .fill (0 )
382
+ .map (() => Array (n ).fill (0 ));
383
+ for (let i = 0 ; i < m ; ++ i ) {
384
+ for (let j = 0 ; j < n ; ++ j ) {
385
+ for (let k = 0 ; k < a [0 ].length ; ++ k ) {
386
+ c [i ][j ] += a [i ][k ] * b [k ][j ];
387
+ }
388
+ }
389
+ }
390
+ return c ;
391
+ }
392
+
393
+ function pow(a : number [][], n : number ): number [][] {
394
+ let res = [
395
+ [1 , 1 ],
396
+ [0 , 0 ],
397
+ ];
398
+ while (n ) {
399
+ if (n & 1 ) {
400
+ res = mul (res , a );
401
+ }
402
+ a = mul (a , a );
403
+ n >>= 1 ;
404
+ }
405
+ return res ;
406
+ }
407
+ ```
408
+
157
409
### ** Rust**
158
410
159
411
``` rust
0 commit comments