@@ -78,32 +78,281 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3552.Gr
78
78
79
79
<!-- solution:start -->
80
80
81
- ### 方法一
81
+ ### 方法一:0-1 BFS
82
+
83
+ 我们可以使用 0-1 BFS 来解决这个问题。我们从左上角单元格开始,使用双端队列来存储当前单元格的坐标。每次从队列中取出一个单元格,我们会检查它的四个相邻单元格,如果相邻单元格是空单元格且没有被访问过,我们就将它加入队列,并更新它的距离。
84
+
85
+ 如果相邻单元格是一个传送门,我们就将它加入队列的前面,并更新它的距离。我们还需要维护一个字典来存储每个传送门的位置,以便在使用传送门时能够快速找到它们。
86
+
87
+ 我们还需要一个二维数组来存储每个单元格的距离,初始值为无穷大。我们将起点的距离设置为 0,然后开始 BFS。
88
+
89
+ 在 BFS 的过程中,我们会检查每个单元格是否是终点,如果是,就返回它的距离。如果队列为空,说明无法到达终点,返回 -1。
90
+
91
+ 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩阵的行数和列数。
82
92
83
93
<!-- tabs:start -->
84
94
85
95
#### Python3
86
96
87
97
``` python
88
-
98
+ class Solution :
99
+ def minMoves (self , matrix : List[str ]) -> int :
100
+ m, n = len (matrix), len (matrix[0 ])
101
+ g = defaultdict(list )
102
+ for i, row in enumerate (matrix):
103
+ for j, c in enumerate (row):
104
+ if c.isalpha():
105
+ g[c].append((i, j))
106
+ dirs = (- 1 , 0 , 1 , 0 , - 1 )
107
+ dist = [[inf] * n for _ in range (m)]
108
+ dist[0 ][0 ] = 0
109
+ q = deque([(0 , 0 )])
110
+ while q:
111
+ i, j = q.popleft()
112
+ d = dist[i][j]
113
+ if i == m - 1 and j == n - 1 :
114
+ return d
115
+ c = matrix[i][j]
116
+ if c in g:
117
+ for x, y in g[c]:
118
+ if d < dist[x][y]:
119
+ dist[x][y] = d
120
+ q.appendleft((x, y))
121
+ del g[c]
122
+ for a, b in pairwise(dirs):
123
+ x, y = i + a, j + b
124
+ if (
125
+ 0 <= x < m
126
+ and 0 <= y < n
127
+ and matrix[x][y] != " #"
128
+ and d + 1 < dist[x][y]
129
+ ):
130
+ dist[x][y] = d + 1
131
+ q.append((x, y))
132
+ return - 1
89
133
```
90
134
91
135
#### Java
92
136
93
137
``` java
94
-
138
+ class Solution {
139
+ public int minMoves (String [] matrix ) {
140
+ int m = matrix. length, n = matrix[0 ]. length();
141
+ Map<Character , List<int[]> > g = new HashMap<> ();
142
+ for (int i = 0 ; i < m; i++ ) {
143
+ String row = matrix[i];
144
+ for (int j = 0 ; j < n; j++ ) {
145
+ char c = row. charAt(j);
146
+ if (Character . isAlphabetic(c)) {
147
+ g. computeIfAbsent(c, k - > new ArrayList<> ()). add(new int [] {i, j});
148
+ }
149
+ }
150
+ }
151
+ int [] dirs = {- 1 , 0 , 1 , 0 , - 1 };
152
+ int INF = Integer . MAX_VALUE / 2 ;
153
+ int [][] dist = new int [m][n];
154
+ for (int [] arr : dist) Arrays . fill(arr, INF );
155
+ dist[0 ][0 ] = 0 ;
156
+ Deque<int[]> q = new ArrayDeque<> ();
157
+ q. add(new int [] {0 , 0 });
158
+ while (! q. isEmpty()) {
159
+ int [] cur = q. pollFirst();
160
+ int i = cur[0 ], j = cur[1 ];
161
+ int d = dist[i][j];
162
+ if (i == m - 1 && j == n - 1 ) return d;
163
+ char c = matrix[i]. charAt(j);
164
+ if (g. containsKey(c)) {
165
+ for (int [] pos : g. get(c)) {
166
+ int x = pos[0 ], y = pos[1 ];
167
+ if (d < dist[x][y]) {
168
+ dist[x][y] = d;
169
+ q. addFirst(new int [] {x, y});
170
+ }
171
+ }
172
+ g. remove(c);
173
+ }
174
+ for (int idx = 0 ; idx < 4 ; idx++ ) {
175
+ int a = dirs[idx], b = dirs[idx + 1 ];
176
+ int x = i + a, y = j + b;
177
+ if (0 <= x && x < m && 0 <= y && y < n && matrix[x]. charAt(y) != ' #'
178
+ && d + 1 < dist[x][y]) {
179
+ dist[x][y] = d + 1 ;
180
+ q. addLast(new int [] {x, y});
181
+ }
182
+ }
183
+ }
184
+ return - 1 ;
185
+ }
186
+ }
95
187
```
96
188
97
189
#### C++
98
190
99
191
``` cpp
100
-
192
+ class Solution {
193
+ public:
194
+ int minMoves(vector<string >& matrix) {
195
+ int m = matrix.size(), n = matrix[ 0] .size();
196
+ unordered_map<char, vector<pair<int, int>>> g;
197
+ for (int i = 0; i < m; ++i)
198
+ for (int j = 0; j < n; ++j) {
199
+ char c = matrix[ i] [ j ] ;
200
+ if (isalpha(c)) g[ c] .push_back({i, j});
201
+ }
202
+ int dirs[ 5] = {-1, 0, 1, 0, -1};
203
+ int INF = numeric_limits<int >::max() / 2;
204
+ vector<vector<int >> dist(m, vector<int >(n, INF));
205
+ dist[ 0] [ 0 ] = 0;
206
+ deque<pair<int, int>> q;
207
+ q.push_back({0, 0});
208
+ while (!q.empty()) {
209
+ auto [ i, j] = q.front();
210
+ q.pop_front();
211
+ int d = dist[ i] [ j ] ;
212
+ if (i == m - 1 && j == n - 1) return d;
213
+ char c = matrix[ i] [ j ] ;
214
+ if (g.count(c)) {
215
+ for (auto [ x, y] : g[ c] )
216
+ if (d < dist[ x] [ y ] ) {
217
+ dist[ x] [ y ] = d;
218
+ q.push_front({x, y});
219
+ }
220
+ g.erase(c);
221
+ }
222
+ for (int idx = 0; idx < 4; ++idx) {
223
+ int x = i + dirs[ idx] , y = j + dirs[ idx + 1] ;
224
+ if (0 <= x && x < m && 0 <= y && y < n && matrix[ x] [ y ] != '#' && d + 1 < dist[ x] [ y ] ) {
225
+ dist[ x] [ y ] = d + 1;
226
+ q.push_back({x, y});
227
+ }
228
+ }
229
+ }
230
+ return -1;
231
+ }
232
+ };
101
233
```
102
234
103
235
#### Go
104
236
105
237
```go
238
+ type pair struct{ x, y int }
239
+
240
+ func minMoves(matrix []string) int {
241
+ m, n := len(matrix), len(matrix[0])
242
+ g := make(map[rune][]pair)
243
+ for i := 0; i < m; i++ {
244
+ for j, c := range matrix[i] {
245
+ if unicode.IsLetter(c) {
246
+ g[c] = append(g[c], pair{i, j})
247
+ }
248
+ }
249
+ }
250
+ dirs := []int{-1, 0, 1, 0, -1}
251
+ INF := 1 << 30
252
+ dist := make([][]int, m)
253
+ for i := range dist {
254
+ dist[i] = make([]int, n)
255
+ for j := range dist[i] {
256
+ dist[i][j] = INF
257
+ }
258
+ }
259
+ dist[0][0] = 0
260
+ q := list.New()
261
+ q.PushBack(pair{0, 0})
262
+ for q.Len() > 0 {
263
+ cur := q.Remove(q.Front()).(pair)
264
+ i, j := cur.x, cur.y
265
+ d := dist[i][j]
266
+ if i == m-1 && j == n-1 {
267
+ return d
268
+ }
269
+ c := rune(matrix[i][j])
270
+ if v, ok := g[c]; ok {
271
+ for _, p := range v {
272
+ x, y := p.x, p.y
273
+ if d < dist[x][y] {
274
+ dist[x][y] = d
275
+ q.PushFront(pair{x, y})
276
+ }
277
+ }
278
+ delete(g, c)
279
+ }
280
+ for idx := 0; idx < 4; idx++ {
281
+ x, y := i+dirs[idx], j+dirs[idx+1]
282
+ if 0 <= x && x < m && 0 <= y && y < n && matrix[x][y] != '#' && d+1 < dist[x][y] {
283
+ dist[x][y] = d + 1
284
+ q.PushBack(pair{x, y})
285
+ }
286
+ }
287
+ }
288
+ return -1
289
+ }
290
+ ```
106
291
292
+ #### TypeScript
293
+
294
+ ``` ts
295
+ function minMoves(matrix : string []): number {
296
+ const m = matrix .length ,
297
+ n = matrix [0 ].length ;
298
+ const g = new Map <string , [number , number ][]>();
299
+ for (let i = 0 ; i < m ; i ++ ) {
300
+ for (let j = 0 ; j < n ; j ++ ) {
301
+ const c = matrix [i ][j ];
302
+ if (/ ^ [A-Za-z ] $ / .test (c )) {
303
+ if (! g .has (c )) g .set (c , []);
304
+ g .get (c )! .push ([i , j ]);
305
+ }
306
+ }
307
+ }
308
+
309
+ const dirs = [- 1 , 0 , 1 , 0 , - 1 ];
310
+ const INF = Number .MAX_SAFE_INTEGER;
311
+ const dist: number [][] = Array .from ({ length: m }, () => Array (n ).fill (INF ));
312
+ dist [0 ][0 ] = 0 ;
313
+
314
+ const cap = m * n * 2 + 5 ;
315
+ const dq = new Array <[number , number ]>(cap );
316
+ let l = cap >> 1 ,
317
+ r = cap >> 1 ;
318
+ const pushFront = (v : [number , number ]) => {
319
+ dq [-- l ] = v ;
320
+ };
321
+ const pushBack = (v : [number , number ]) => {
322
+ dq [r ++ ] = v ;
323
+ };
324
+ const popFront = (): [number , number ] => dq [l ++ ];
325
+ const empty = () => l === r ;
326
+
327
+ pushBack ([0 , 0 ]);
328
+
329
+ while (! empty ()) {
330
+ const [i, j] = popFront ();
331
+ const d = dist [i ][j ];
332
+ if (i === m - 1 && j === n - 1 ) return d ;
333
+
334
+ const c = matrix [i ][j ];
335
+ if (g .has (c )) {
336
+ for (const [x, y] of g .get (c )! ) {
337
+ if (d < dist [x ][y ]) {
338
+ dist [x ][y ] = d ;
339
+ pushFront ([x , y ]);
340
+ }
341
+ }
342
+ g .delete (c );
343
+ }
344
+
345
+ for (let idx = 0 ; idx < 4 ; idx ++ ) {
346
+ const x = i + dirs [idx ],
347
+ y = j + dirs [idx + 1 ];
348
+ if (0 <= x && x < m && 0 <= y && y < n && matrix [x ][y ] !== ' #' && d + 1 < dist [x ][y ]) {
349
+ dist [x ][y ] = d + 1 ;
350
+ pushBack ([x , y ]);
351
+ }
352
+ }
353
+ }
354
+ return - 1 ;
355
+ }
107
356
```
108
357
109
358
<!-- tabs: end -->
0 commit comments