Skip to content

Commit 8c1d32f

Browse files
authored
feat: add solutions to lc problem: No.0120 (#4747)
1 parent 57032bd commit 8c1d32f

File tree

13 files changed

+154
-188
lines changed

13 files changed

+154
-188
lines changed

solution/0100-0199/0120.Triangle/README.md

Lines changed: 51 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,11 @@ tags:
7373
我们定义 $f[i][j]$ 表示从三角形底部走到位置 $(i, j)$ 的最小路径和。这里的位置 $(i, j)$ 指的是三角形中第 $i$ 行第 $j$ 列(均从 $0$ 开始编号)的位置。那么我们有如下的状态转移方程:
7474

7575
$$
76-
f[i][j] = \min(f[i + 1][j], f[i + 1][j + 1]) + triangle[i][j]
76+
f[i][j] = \min(f[i + 1][j], f[i + 1][j + 1]) + \text{triangle}[i][j]
7777
$$
7878

7979
答案即为 $f[0][0]$。
8080

81-
我们注意到,状态 $f[i][j]$ 仅与状态 $f[i + 1][j]$ 和状态 $f[i + 1][j + 1]$ 有关,因此我们可以使用一维数组代替二维数组,将空间复杂度从 $O(n^2)$ 降低至 $O(n)$。
82-
83-
时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是三角形的行数。
84-
85-
更进一步,我们还可以直接复用 $triangle$ 作为 $f$ 数组,这样就无需再额外创建 $f$ 数组,空间复杂度降低至 $O(1)$。
86-
8781
<!-- tabs:start -->
8882

8983
#### Python3
@@ -105,13 +99,13 @@ class Solution:
10599
class Solution {
106100
public int minimumTotal(List<List<Integer>> triangle) {
107101
int n = triangle.size();
108-
int[] f = new int[n + 1];
102+
int[][] f = new int[n + 1][n + 1];
109103
for (int i = n - 1; i >= 0; --i) {
110104
for (int j = 0; j <= i; ++j) {
111-
f[j] = Math.min(f[j], f[j + 1]) + triangle.get(i).get(j);
105+
f[i][j] = Math.min(f[i + 1][j], f[i + 1][j + 1]) + triangle.get(i).get(j);
112106
}
113107
}
114-
return f[0];
108+
return f[0][0];
115109
}
116110
}
117111
```
@@ -123,14 +117,13 @@ class Solution {
123117
public:
124118
int minimumTotal(vector<vector<int>>& triangle) {
125119
int n = triangle.size();
126-
int f[n + 1];
127-
memset(f, 0, sizeof(f));
128-
for (int i = n - 1; ~i; --i) {
120+
vector<vector<int>> f(n + 1, vector<int>(n + 1, 0));
121+
for (int i = n - 1; i >= 0; --i) {
129122
for (int j = 0; j <= i; ++j) {
130-
f[j] = min(f[j], f[j + 1]) + triangle[i][j];
123+
f[i][j] = min(f[i + 1][j], f[i + 1][j + 1]) + triangle[i][j];
131124
}
132125
}
133-
return f[0];
126+
return f[0][0];
134127
}
135128
};
136129
```
@@ -140,13 +133,16 @@ public:
140133
```go
141134
func minimumTotal(triangle [][]int) int {
142135
n := len(triangle)
143-
f := make([]int, n+1)
136+
f := make([][]int, n+1)
137+
for i := range f {
138+
f[i] = make([]int, n+1)
139+
}
144140
for i := n - 1; i >= 0; i-- {
145141
for j := 0; j <= i; j++ {
146-
f[j] = min(f[j], f[j+1]) + triangle[i][j]
142+
f[i][j] = min(f[i+1][j], f[i+1][j+1]) + triangle[i][j]
147143
}
148144
}
149-
return f[0]
145+
return f[0][0]
150146
}
151147
```
152148

@@ -155,13 +151,13 @@ func minimumTotal(triangle [][]int) int {
155151
```ts
156152
function minimumTotal(triangle: number[][]): number {
157153
const n = triangle.length;
158-
const f: number[] = Array(n + 1).fill(0);
159-
for (let i = n - 1; ~i; --i) {
154+
const f: number[][] = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0));
155+
for (let i = n - 1; i >= 0; --i) {
160156
for (let j = 0; j <= i; ++j) {
161-
f[j] = Math.min(f[j], f[j + 1]) + triangle[i][j];
157+
f[i][j] = Math.min(f[i + 1][j], f[i + 1][j + 1]) + triangle[i][j];
162158
}
163159
}
164-
return f[0];
160+
return f[0][0];
165161
}
166162
```
167163

@@ -171,13 +167,13 @@ function minimumTotal(triangle: number[][]): number {
171167
impl Solution {
172168
pub fn minimum_total(triangle: Vec<Vec<i32>>) -> i32 {
173169
let n = triangle.len();
174-
let mut f = vec![0; n + 1];
170+
let mut f = vec![vec![0; n + 1]; n + 1];
175171
for i in (0..n).rev() {
176172
for j in 0..=i {
177-
f[j] = f[j].min(f[j + 1]) + triangle[i][j];
173+
f[i][j] = f[i + 1][j].min(f[i + 1][j + 1]) + triangle[i][j];
178174
}
179175
}
180-
f[0]
176+
f[0][0]
181177
}
182178
}
183179
```
@@ -188,7 +184,11 @@ impl Solution {
188184

189185
<!-- solution:start -->
190186

191-
### 方法二
187+
### 方法二:动态规划(空间优化)
188+
189+
我们注意到,状态 $f[i][j]$ 仅与状态 $f[i + 1][j]$ 和状态 $f[i + 1][j + 1]$ 有关,因此我们可以使用一维数组代替二维数组,将空间复杂度从 $O(n^2)$ 降低至 $O(n)$。
190+
191+
时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是三角形的行数。
192192

193193
<!-- tabs:start -->
194194

@@ -210,14 +210,14 @@ class Solution:
210210
```java
211211
class Solution {
212212
public int minimumTotal(List<List<Integer>> triangle) {
213-
for (int i = triangle.size() - 2; i >= 0; --i) {
213+
int n = triangle.size();
214+
int[] f = new int[n + 1];
215+
for (int i = n - 1; i >= 0; --i) {
214216
for (int j = 0; j <= i; ++j) {
215-
int x = triangle.get(i).get(j);
216-
int y = Math.min(triangle.get(i + 1).get(j), triangle.get(i + 1).get(j + 1));
217-
triangle.get(i).set(j, x + y);
217+
f[j] = Math.min(f[j], f[j + 1]) + triangle.get(i).get(j);
218218
}
219219
}
220-
return triangle.get(0).get(0);
220+
return f[0];
221221
}
222222
}
223223
```
@@ -228,12 +228,14 @@ class Solution {
228228
class Solution {
229229
public:
230230
int minimumTotal(vector<vector<int>>& triangle) {
231-
for (int i = triangle.size() - 2; ~i; --i) {
231+
int n = triangle.size();
232+
vector<int> f(n + 1, 0);
233+
for (int i = n - 1; i >= 0; --i) {
232234
for (int j = 0; j <= i; ++j) {
233-
triangle[i][j] += min(triangle[i + 1][j], triangle[i + 1][j + 1]);
235+
f[j] = min(f[j], f[j + 1]) + triangle[i][j];
234236
}
235237
}
236-
return triangle[0][0];
238+
return f[0];
237239
}
238240
};
239241
```
@@ -242,25 +244,29 @@ public:
242244
243245
```go
244246
func minimumTotal(triangle [][]int) int {
245-
for i := len(triangle) - 2; i >= 0; i-- {
247+
n := len(triangle)
248+
f := make([]int, n+1)
249+
for i := n - 1; i >= 0; i-- {
246250
for j := 0; j <= i; j++ {
247-
triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1])
251+
f[j] = min(f[j], f[j+1]) + triangle[i][j]
248252
}
249253
}
250-
return triangle[0][0]
254+
return f[0]
251255
}
252256
```
253257

254258
#### TypeScript
255259

256260
```ts
257261
function minimumTotal(triangle: number[][]): number {
258-
for (let i = triangle.length - 2; ~i; --i) {
262+
const n = triangle.length;
263+
const f: number[] = Array(n + 1).fill(0);
264+
for (let i = n - 1; i >= 0; --i) {
259265
for (let j = 0; j <= i; ++j) {
260-
triangle[i][j] += Math.min(triangle[i + 1][j], triangle[i + 1][j + 1]);
266+
f[j] = Math.min(f[j], f[j + 1]) + triangle[i][j];
261267
}
262268
}
263-
return triangle[0][0];
269+
return f[0];
264270
}
265271
```
266272

@@ -269,13 +275,14 @@ function minimumTotal(triangle: number[][]): number {
269275
```rust
270276
impl Solution {
271277
pub fn minimum_total(triangle: Vec<Vec<i32>>) -> i32 {
272-
let mut triangle = triangle;
273-
for i in (0..triangle.len() - 1).rev() {
278+
let n = triangle.len();
279+
let mut f = vec![0; n + 1];
280+
for i in (0..n).rev() {
274281
for j in 0..=i {
275-
triangle[i][j] += triangle[i + 1][j].min(triangle[i + 1][j + 1]);
282+
f[j] = f[j].min(f[j + 1]) + triangle[i][j];
276283
}
277284
}
278-
triangle[0][0]
285+
f[0]
279286
}
280287
}
281288
```
@@ -284,28 +291,4 @@ impl Solution {
284291

285292
<!-- solution:end -->
286293

287-
<!-- solution:start -->
288-
289-
### 方法三
290-
291-
<!-- tabs:start -->
292-
293-
#### Python3
294-
295-
```python
296-
class Solution:
297-
def minimumTotal(self, triangle: List[List[int]]) -> int:
298-
n = len(triangle)
299-
for i in range(n - 2, -1, -1):
300-
for j in range(i + 1):
301-
triangle[i][j] = (
302-
min(triangle[i + 1][j], triangle[i + 1][j + 1]) + triangle[i][j]
303-
)
304-
return triangle[0][0]
305-
```
306-
307-
<!-- tabs:end -->
308-
309-
<!-- solution:end -->
310-
311294
<!-- problem:end -->

0 commit comments

Comments
 (0)