58
58
59
59
<!-- 这里可写通用的实现逻辑 -->
60
60
61
- 并查集。
61
+ ** 方法一:并查集**
62
+
63
+ 对于本题,每个格子当做图的一个节点,把相邻两个格子的高度差绝对值当做边的权重,因此本题是求解从最左上角的节点到最右下角的节点的连通性问题。
64
+
65
+ 先把图中所有边去掉,然后按照边的权重从小到大,逐个把边添加上。如果在某一次添加一条边时,最左上角和最右下角的节点连通了,那么该边的权重就是题目的最小体力消耗值。
62
66
63
67
并查集模板:
64
68
@@ -119,34 +123,35 @@ p[find(a)] = find(b)
119
123
d[find(a)] = distance
120
124
```
121
125
122
- 对于本题,每个格子当做图的一个节点,把相邻两个格子的高度差绝对值当做边的权重,因此本题是求解从最左上角的节点到最右下角的节点的连通性问题。
126
+ ** 方法二:二分查找 + BFS **
123
127
124
- 先把图中所有边去掉,然后按照边的权重从小到大,逐个把边添加上。如果在某一次添加一条边时,最左上角和最右下角的节点连通了,那么该边的权重就是题目的最小体力消耗值 。
128
+ 二分枚举体力消耗值,用 BFS 找到满足条件的最小消耗值即可 。
125
129
126
130
<!-- tabs:start -->
127
131
128
132
### ** Python3**
129
133
130
134
<!-- 这里可写当前语言的特殊实现逻辑 -->
131
135
136
+ 并查集:
137
+
132
138
``` python
133
139
class Solution :
134
140
def minimumEffortPath (self , heights : List[List[int ]]) -> int :
135
- m, n = len (heights), len (heights[0 ])
136
- p = list (range (m * n))
137
-
138
141
def find (x ):
139
142
if p[x] != x:
140
143
p[x] = find(p[x])
141
144
return p[x]
142
145
146
+ m, n = len (heights), len (heights[0 ])
147
+ p = list (range (m * n))
143
148
e = []
144
149
for i in range (m):
145
150
for j in range (n):
146
151
if i < m - 1 :
147
- e.append([ abs (heights[i][j] - heights[i + 1 ][j]), i * n + j, (i + 1 ) * n + j] )
152
+ e.append(( abs (heights[i][j] - heights[i + 1 ][j]), i * n + j, (i + 1 ) * n + j) )
148
153
if j < n - 1 :
149
- e.append([ abs (heights[i][j] - heights[i][j + 1 ]), i * n + j, i * n + j + 1 ] )
154
+ e.append(( abs (heights[i][j] - heights[i][j + 1 ]), i * n + j, i * n + j + 1 ) )
150
155
e.sort()
151
156
for h, i, j in e:
152
157
p[find(i)] = find(j)
@@ -155,16 +160,44 @@ class Solution:
155
160
return 0
156
161
```
157
162
163
+ 二分查找 + BFS:
164
+
165
+ ``` python
166
+ class Solution :
167
+ def minimumEffortPath (self , heights : List[List[int ]]) -> int :
168
+ m, n = len (heights), len (heights[0 ])
169
+ left, right = 0 , 999999
170
+ while left < right:
171
+ mid = (left + right) >> 1
172
+ q = deque([(0 , 0 )])
173
+ vis = set ([(0 , 0 )])
174
+ while q:
175
+ i, j = q.popleft()
176
+ for a, b in [[0 , 1 ], [0 , - 1 ], [1 , 0 ], [- 1 , 0 ]]:
177
+ x, y = i + a, j + b
178
+ if 0 <= x < m and 0 <= y < n and (x, y) not in vis and abs (heights[i][j] - heights[x][y]) <= mid:
179
+ q.append((x, y))
180
+ vis.add((x, y))
181
+ if (m - 1 , n - 1 ) in vis:
182
+ right = mid
183
+ else :
184
+ left = mid + 1
185
+ return left
186
+ ```
187
+
158
188
### ** Java**
159
189
160
190
<!-- 这里可写当前语言的特殊实现逻辑 -->
161
191
192
+ 并查集:
193
+
162
194
``` java
163
195
class Solution {
164
196
private int [] p;
165
197
166
198
public int minimumEffortPath (int [][] heights ) {
167
- int m = heights. length, n = heights[0 ]. length;
199
+ int m = heights. length;
200
+ int n = heights[0 ]. length;
168
201
p = new int [m * n];
169
202
for (int i = 0 ; i < p. length; ++ i) {
170
203
p[i] = i;
@@ -200,8 +233,48 @@ class Solution {
200
233
}
201
234
```
202
235
236
+ 二分查找 + BFS:
237
+
238
+ ``` java
239
+ class Solution {
240
+ public int minimumEffortPath (int [][] heights ) {
241
+ int m = heights. length;
242
+ int n = heights[0 ]. length;
243
+ int left = 0 ;
244
+ int right = 999999 ;
245
+ int [] dirs = {- 1 , 0 , 1 , 0 , - 1 };
246
+ while (left < right) {
247
+ int mid = (left + right) >> 1 ;
248
+ boolean [][] vis = new boolean [m][n];
249
+ vis[0 ][0 ] = true ;
250
+ Deque<int[]> q = new ArrayDeque<> ();
251
+ q. offer(new int []{0 , 0 });
252
+ while (! q. isEmpty()) {
253
+ int [] p = q. poll();
254
+ int i = p[0 ], j = p[1 ];
255
+ for (int k = 0 ; k < 4 ; ++ k) {
256
+ int x = i + dirs[k], y = j + dirs[k + 1 ];
257
+ if (x >= 0 && x < m && y >= 0 && y < n && ! vis[x][y] && Math . abs(heights[i][j] - heights[x][y]) <= mid) {
258
+ q. offer(new int []{x, y});
259
+ vis[x][y] = true ;
260
+ }
261
+ }
262
+ }
263
+ if (vis[m - 1 ][n - 1 ]) {
264
+ right = mid;
265
+ } else {
266
+ left = mid + 1 ;
267
+ }
268
+ }
269
+ return left;
270
+ }
271
+ }
272
+ ```
273
+
203
274
### ** C++**
204
275
276
+ 并查集:
277
+
205
278
``` cpp
206
279
class Solution {
207
280
public:
@@ -221,7 +294,7 @@ public:
221
294
}
222
295
}
223
296
sort (edges.begin(), edges.end());
224
- for (auto e : edges)
297
+ for (auto& e : edges)
225
298
{
226
299
int i = e[ 1] , j = e[ 2] ;
227
300
p[ find(i)] = find(j);
@@ -237,26 +310,71 @@ public:
237
310
};
238
311
```
239
312
313
+ 二分查找 + BFS:
314
+
315
+ ```cpp
316
+ class Solution {
317
+ public:
318
+ int minimumEffortPath(vector<vector<int>>& heights) {
319
+ int m = heights.size(), n = heights[0].size();
320
+ int left = 0, right = 999999;
321
+ vector<int> dirs = {-1, 0, 1, 0, -1};
322
+ while (left < right)
323
+ {
324
+ int mid = (left + right) >> 1;
325
+ vector<vector<bool>> vis(m, vector<bool>(n));
326
+ vis[0][0] = true;
327
+ queue<pair<int, int>> q;
328
+ q.push({0, 0});
329
+ while (!q.empty())
330
+ {
331
+ auto [i, j] = q.front();
332
+ q.pop();
333
+ for (int k = 0; k < 4; ++k)
334
+ {
335
+ int x = i + dirs[k], y = j + dirs[k + 1];
336
+ if (x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && abs(heights[i][j] - heights[x][y]) <= mid)
337
+ {
338
+ q.push({x, y});
339
+ vis[x][y] = true;
340
+ }
341
+ }
342
+ }
343
+ if (vis[m - 1][n - 1]) right = mid;
344
+ else left = mid + 1;
345
+ }
346
+ return left;
347
+ }
348
+ };
349
+ ```
350
+
240
351
### ** Go**
241
352
242
- ```go
243
- var p []int
353
+ 并查集:
244
354
355
+ ``` go
245
356
func minimumEffortPath (heights [][]int ) int {
246
357
m , n := len (heights), len (heights[0 ])
247
- p = make([]int, m*n)
248
- for i := 0; i < len(p); i++ {
358
+ p : = make ([]int , m*n)
359
+ for i := range p {
249
360
p[i] = i
250
361
}
251
- var edges [][]int
252
- for i := 0; i < m; i++ {
253
- for j := 0; j < n; j++ {
362
+ var find func (x int ) int
363
+ find = func (x int ) int {
364
+ if p[x] != x {
365
+ p[x] = find (p[x])
366
+ }
367
+ return p[x]
368
+ }
369
+ edges := [][]int {}
370
+ for i , row := range heights {
371
+ for j , h := range row {
254
372
if i < m-1 {
255
- s := []int{abs(heights[i][j] - heights[i+1][j]), i*n + j, (i+1)*n + j}
373
+ s := []int {abs (h - heights[i+1 ][j]), i*n + j, (i+1 )*n + j}
256
374
edges = append (edges, s)
257
375
}
258
376
if j < n-1 {
259
- s := []int{abs(heights[i][j] - heights[i] [j+1]), i*n + j, i*n + j + 1}
377
+ s := []int {abs (h - row [j+1 ]), i*n + j, i*n + j + 1 }
260
378
edges = append (edges, s)
261
379
}
262
380
}
@@ -274,11 +392,48 @@ func minimumEffortPath(heights [][]int) int {
274
392
return 0
275
393
}
276
394
277
- func find(x int) int {
278
- if p[x] != x {
279
- p[x] = find(p[x])
395
+ func abs (x int ) int {
396
+ if x > 0 {
397
+ return x
398
+ }
399
+ return -x
400
+ }
401
+ ```
402
+
403
+ 二分查找 + BFS:
404
+
405
+ ``` go
406
+ func minimumEffortPath (heights [][]int ) int {
407
+ m , n := len (heights), len (heights[0 ])
408
+ left , right := 0 , 999999
409
+ dirs := []int {-1 , 0 , 1 , 0 , -1 }
410
+ for left < right {
411
+ mid := (left + right) >> 1
412
+ vis := make ([][]bool , m)
413
+ for i := range vis {
414
+ vis[i] = make ([]bool , n)
415
+ }
416
+ vis[0 ][0 ] = true
417
+ q := [][]int {{0 , 0 }}
418
+ for len (q) > 0 {
419
+ p := q[0 ]
420
+ q = q[1 :]
421
+ i , j := p[0 ], p[1 ]
422
+ for k := 0 ; k < 4 ; k++ {
423
+ x , y := i+dirs[k], j+dirs[k+1 ]
424
+ if x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && abs (heights[i][j]-heights[x][y]) <= mid {
425
+ q = append (q, []int {x, y})
426
+ vis[x][y] = true
427
+ }
428
+ }
429
+ }
430
+ if vis[m-1 ][n-1 ] {
431
+ right = mid
432
+ } else {
433
+ left = mid + 1
434
+ }
280
435
}
281
- return p[x]
436
+ return left
282
437
}
283
438
284
439
func abs (x int ) int {
0 commit comments