@@ -65,7 +65,177 @@ tags:
65
65
66
66
<!-- solution:start -->
67
67
68
- ### 方法一:动态规划
68
+ ### 方法一:记忆化搜索
69
+
70
+ 我们设计一个函数 $\textit{dfs}(i)$,表示从第 $i$ 个阶梯开始爬楼梯所需要的最小花费。那么答案为 $\min(\textit{dfs}(0), \textit{dfs}(1))$。
71
+
72
+ 函数 $\textit{dfs}(i)$ 的执行过程如下:
73
+
74
+ - 如果 $i \ge \textit{len(cost)}$,表示当前位置已经超过了楼梯顶部,不需要再爬楼梯,返回 $0$;
75
+ - 否则,我们可以选择爬 $1$ 级楼梯,花费为 $\textit{cost}[ i] $,然后递归调用 $\textit{dfs}(i + 1)$;也可以选择爬 $2$ 级楼梯,花费为 $\textit{cost}[ i] $,然后递归调用 $\textit{dfs}(i + 2)$;
76
+ - 返回两种方案中的最小花费。
77
+
78
+ 为了避免重复计算,我们使用记忆化搜索的方法,将已经计算过的结果保存在数组或哈希表中。
79
+
80
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{cost}$ 的长度。
81
+
82
+ <!-- tabs:start -->
83
+
84
+ #### Python3
85
+
86
+ ``` python
87
+ class Solution :
88
+ def minCostClimbingStairs (self , cost : List[int ]) -> int :
89
+ @cache
90
+ def dfs (i : int ) -> int :
91
+ if i >= len (cost):
92
+ return 0
93
+ return cost[i] + min (dfs(i + 1 ), dfs(i + 2 ))
94
+
95
+ return min (dfs(0 ), dfs(1 ))
96
+ ```
97
+
98
+ #### Java
99
+
100
+ ``` java
101
+ class Solution {
102
+ private Integer [] f;
103
+ private int [] cost;
104
+
105
+ public int minCostClimbingStairs (int [] cost ) {
106
+ this . cost = cost;
107
+ f = new Integer [cost. length];
108
+ return Math . min(dfs(0 ), dfs(1 ));
109
+ }
110
+
111
+ private int dfs (int i ) {
112
+ if (i >= cost. length) {
113
+ return 0 ;
114
+ }
115
+ if (f[i] == null ) {
116
+ f[i] = cost[i] + Math . min(dfs(i + 1 ), dfs(i + 2 ));
117
+ }
118
+ return f[i];
119
+ }
120
+ }
121
+ ```
122
+
123
+ #### C++
124
+
125
+ ``` cpp
126
+ class Solution {
127
+ public:
128
+ int minCostClimbingStairs(vector<int >& cost) {
129
+ int n = cost.size();
130
+ int f[ n] ;
131
+ memset(f, -1, sizeof(f));
132
+ auto dfs = [ &] (auto&& dfs, int i) -> int {
133
+ if (i >= n) {
134
+ return 0;
135
+ }
136
+ if (f[ i] < 0) {
137
+ f[ i] = cost[ i] + min(dfs(dfs, i + 1), dfs(dfs, i + 2));
138
+ }
139
+ return f[ i] ;
140
+ };
141
+ return min(dfs(dfs, 0), dfs(dfs, 1));
142
+ }
143
+ };
144
+ ```
145
+
146
+ #### Go
147
+
148
+ ```go
149
+ func minCostClimbingStairs(cost []int) int {
150
+ n := len(cost)
151
+ f := make([]int, n)
152
+ for i := range f {
153
+ f[i] = -1
154
+ }
155
+ var dfs func(int) int
156
+ dfs = func(i int) int {
157
+ if i >= n {
158
+ return 0
159
+ }
160
+ if f[i] < 0 {
161
+ f[i] = cost[i] + min(dfs(i+1), dfs(i+2))
162
+ }
163
+ return f[i]
164
+ }
165
+ return min(dfs(0), dfs(1))
166
+ }
167
+ ```
168
+
169
+ #### TypeScript
170
+
171
+ ``` ts
172
+ function minCostClimbingStairs(cost : number []): number {
173
+ const n = cost .length ;
174
+ const f: number [] = Array (n ).fill (- 1 );
175
+ const dfs = (i : number ): number => {
176
+ if (i >= n ) {
177
+ return 0 ;
178
+ }
179
+ if (f [i ] < 0 ) {
180
+ f [i ] = cost [i ] + Math .min (dfs (i + 1 ), dfs (i + 2 ));
181
+ }
182
+ return f [i ];
183
+ };
184
+ return Math .min (dfs (0 ), dfs (1 ));
185
+ }
186
+ ```
187
+
188
+ #### Rust
189
+
190
+ ``` rust
191
+ impl Solution {
192
+ pub fn min_cost_climbing_stairs (cost : Vec <i32 >) -> i32 {
193
+ let n = cost . len ();
194
+ let mut f = vec! [- 1 ; n ];
195
+
196
+ fn dfs (i : usize , cost : & Vec <i32 >, f : & mut Vec <i32 >, n : usize ) -> i32 {
197
+ if i >= n {
198
+ return 0 ;
199
+ }
200
+ if f [i ] < 0 {
201
+ let next1 = dfs (i + 1 , cost , f , n );
202
+ let next2 = dfs (i + 2 , cost , f , n );
203
+ f [i ] = cost [i ] + next1 . min (next2 );
204
+ }
205
+ f [i ]
206
+ }
207
+
208
+ dfs (0 , & cost , & mut f , n ). min (dfs (1 , & cost , & mut f , n ))
209
+ }
210
+ }
211
+ ```
212
+
213
+ #### JavaScript
214
+
215
+ ``` js
216
+ function minCostClimbingStairs (cost ) {
217
+ const n = cost .length ;
218
+ const f = Array (n).fill (- 1 );
219
+ const dfs = i => {
220
+ if (i >= n) {
221
+ return 0 ;
222
+ }
223
+ if (f[i] < 0 ) {
224
+ f[i] = cost[i] + Math .min (dfs (i + 1 ), dfs (i + 2 ));
225
+ }
226
+ return f[i];
227
+ };
228
+ return Math .min (dfs (0 ), dfs (1 ));
229
+ }
230
+ ```
231
+
232
+ <!-- tab: end -->
233
+
234
+ <!-- solution: end -->
235
+
236
+ <!-- solution: start -->
237
+
238
+ ### 方法二:动态规划
69
239
70
240
我们定义 $f[ i] $ 表示到达第 $i$ 个阶梯所需要的最小花费,初始时 $f[ 0] = f[ 1] = 0$,答案即为 $f[ n] $。
71
241
77
247
78
248
最终的答案即为 $f[ n] $。
79
249
80
- 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 ` cost ` 的长度。
81
-
82
- 我们注意到,状态转移方程中的 $f[ i] $ 只和 $f[ i - 1] $ 与 $f[ i - 2] $ 有关,因此我们可以使用两个变量 $f$ 和 $g$ 交替地记录 $f[ i - 2] $ 和 $f[ i - 1] $ 的值,这样空间复杂度可以优化到 $O(1)$。
250
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{cost}$ 的长度。
83
251
84
252
<!-- tabs: start -->
85
253
@@ -167,13 +335,28 @@ impl Solution {
167
335
}
168
336
```
169
337
338
+ #### JavaScript
339
+
340
+ ``` js
341
+ function minCostClimbingStairs (cost ) {
342
+ const n = cost .length ;
343
+ const f = Array (n + 1 ).fill (0 );
344
+ for (let i = 2 ; i <= n; ++ i) {
345
+ f[i] = Math .min (f[i - 1 ] + cost[i - 1 ], f[i - 2 ] + cost[i - 2 ]);
346
+ }
347
+ return f[n];
348
+ }
349
+ ```
350
+
170
351
<!-- tabs: end -->
171
352
172
353
<!-- solution: end -->
173
354
174
355
<!-- solution: start -->
175
356
176
- ### 方法二
357
+ ### 方法三:动态规划(空间优化)
358
+
359
+ 我们注意到,状态转移方程中的 $f[ i] $ 只和 $f[ i - 1] $ 与 $f[ i - 2] $ 有关,因此我们可以使用两个变量 $f$ 和 $g$ 交替地记录 $f[ i - 2] $ 和 $f[ i - 1] $ 的值,这样空间复杂度可以优化到 $O(1)$。
177
360
178
361
<!-- tabs: start -->
179
362
@@ -237,12 +420,11 @@ func minCostClimbingStairs(cost []int) int {
237
420
238
421
``` ts
239
422
function minCostClimbingStairs(cost : number []): number {
240
- let a = 0 ,
241
- b = 0 ;
423
+ let [f, g] = [0 , 0 ];
242
424
for (let i = 1 ; i < cost .length ; ++ i ) {
243
- [a , b ] = [b , Math .min (a + cost [i - 1 ], b + cost [i ])];
425
+ [f , g ] = [g , Math .min (f + cost [i - 1 ], g + cost [i ])];
244
426
}
245
- return b ;
427
+ return g ;
246
428
}
247
429
```
248
430
@@ -262,6 +444,18 @@ impl Solution {
262
444
}
263
445
```
264
446
447
+ #### JavaScript
448
+
449
+ ``` js
450
+ function minCostClimbingStairs (cost ) {
451
+ let [f, g] = [0 , 0 ];
452
+ for (let i = 1 ; i < cost .length ; ++ i) {
453
+ [f, g] = [g, Math .min (f + cost[i - 1 ], g + cost[i])];
454
+ }
455
+ return g;
456
+ }
457
+ ```
458
+
265
459
<!-- tabs: end -->
266
460
267
461
<!-- solution: end -->
0 commit comments