Skip to content

Commit eb1c642

Browse files
rain84yanglbme
andauthored
feat: add solutions to lc problem: No.0746 (doocs#3252)
Co-authored-by: Libin YANG <contact@yanglibin.info>
1 parent 4b80b47 commit eb1c642

23 files changed

+600
-85
lines changed

solution/0700-0799/0746.Min Cost Climbing Stairs/README.md

+203-9
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,177 @@ tags:
6565

6666
<!-- solution:start -->
6767

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+
### 方法二:动态规划
69239

70240
我们定义 $f[i]$ 表示到达第 $i$ 个阶梯所需要的最小花费,初始时 $f[0] = f[1] = 0$,答案即为 $f[n]$。
71241

@@ -77,9 +247,7 @@ $$
77247

78248
最终的答案即为 $f[n]$。
79249

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}$ 的长度。
83251

84252
<!-- tabs:start -->
85253

@@ -167,13 +335,28 @@ impl Solution {
167335
}
168336
```
169337

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+
170351
<!-- tabs:end -->
171352

172353
<!-- solution:end -->
173354

174355
<!-- solution:start -->
175356

176-
### 方法二
357+
### 方法三:动态规划(空间优化)
358+
359+
我们注意到,状态转移方程中的 $f[i]$ 只和 $f[i - 1]$ 与 $f[i - 2]$ 有关,因此我们可以使用两个变量 $f$ 和 $g$ 交替地记录 $f[i - 2]$ 和 $f[i - 1]$ 的值,这样空间复杂度可以优化到 $O(1)$。
177360

178361
<!-- tabs:start -->
179362

@@ -237,12 +420,11 @@ func minCostClimbingStairs(cost []int) int {
237420

238421
```ts
239422
function minCostClimbingStairs(cost: number[]): number {
240-
let a = 0,
241-
b = 0;
423+
let [f, g] = [0, 0];
242424
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])];
244426
}
245-
return b;
427+
return g;
246428
}
247429
```
248430

@@ -262,6 +444,18 @@ impl Solution {
262444
}
263445
```
264446

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+
265459
<!-- tabs:end -->
266460

267461
<!-- solution:end -->

0 commit comments

Comments
 (0)