0%

algorithm-graph

简单

岛屿数量

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。



示例 1:

输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
示例 2:

输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3


提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] 的值为 '0' 或 '1'

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
import java.util.LinkedList;
import java.util.Queue;

public class Solution {
public int numIslands(char[][] grid) {
if (grid.length == 0) {
return 0;
}

int c = 0;

int rows = grid.length;
int cols = grid[0].length;

int[][] visited = new int[rows][cols];

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '0') {
continue;
}

if (visited[i][j] > 0) {
continue;
}

// 新岛屿的左上角,计算新岛屿的标号
c++;

// 然后用图的遍历搜索属于当前岛屿的陆地
// bfs
Queue<int[]> queue = new LinkedList<>();

int[] p = new int[] { i, j };
int x = p[0];
int y = p[1];

queue.offer(p);

// 标记为已访问
visited[x][y] = c;

while (!queue.isEmpty()) {
p = queue.poll();
x = p[0];
y = p[1];

int[][] points = new int[][] {
{ x, y - 1 }, { x - 1, y }, { x, y + 1 }, { x + 1, y }
};

for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (grid[x][y] == '0') {
// 无通路,跳过
continue;
}

if (visited[x][y] == 0) {
queue.offer(q);

// 标记为已访问
visited[x][y] = c;
}
}
}
}
}

return c;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ '1', '1', '1', '1', '0' },

{ '1', '1', '0', '1', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '0', '0', '0' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = {
{ '1', '1', '0', '0', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '1', '0', '0' },

{ '0', '0', '0', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 3;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ '1', '1', '1' },
{ '0', '1', '0' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ '1', '1', '1' },
{ '1', '0', '1' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '0', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'0' },
{ '1', '0', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
import java.util.Deque;
import java.util.LinkedList;

public class Solution {
public int numIslands(char[][] grid) {
if (grid.length == 0) {
return 0;
}

int c = 0;

int rows = grid.length;
int cols = grid[0].length;

int[][] visited = new int[rows][cols];

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '0') {
continue;
}

if (visited[i][j] > 0) {
continue;
}

// 新岛屿的左上角,计算新岛屿的标号
c++;

// 然后用图的遍历搜索属于当前岛屿的陆地
// dfs
Deque<int[]> stack = new LinkedList<>();

int[] p = new int[] { i, j };
int x = p[0];
int y = p[1];

// 标记为已访问
visited[x][y] = c;

while (p != null || !stack.isEmpty()) {
if (p != null) {
x = p[0];
y = p[1];

int[][] points = new int[][] {
{ x, y - 1 }, { x - 1, y }, { x, y + 1 }, { x + 1, y }
};

int[] r = null;
for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (grid[x][y] == '0') {
// 无通路,跳过
continue;
}

if (visited[x][y] == 0) {
r = q;

// 标记为已访问
visited[x][y] = c;

break;
}
}

if (r != null) {
stack.push(p); // 保存回退点

p = r; // 前进
} else {
// p = stack.isEmpty() ? null : stack.pop(); // 回溯
p = null; // 在下一次循环时跳转到回溯分支
}
} else {
p = stack.pop(); // 回溯
}
}
}
}

return c;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ '1', '1', '1', '1', '0' },

{ '1', '1', '0', '1', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '0', '0', '0' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = {
{ '1', '1', '0', '0', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '1', '0', '0' },

{ '0', '0', '0', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 3;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ '1', '1', '1' },
{ '0', '1', '0' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ '1', '1', '1' },
{ '1', '0', '1' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '0', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'0' },
{ '1', '0', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

解法2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
public class Solution {
public int numIslands(char[][] grid) {
if (grid.length == 0) {
return 0;
}

int c = 0;

int rows = grid.length;
int cols = grid[0].length;

int[][] visited = new int[rows][cols];

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '0') {
continue;
}

if (visited[i][j] > 0) {
continue;
}

// 新岛屿的左上角,计算新岛屿的标号
c++;

// 然后用图的遍历搜索属于当前岛屿的陆地
// dfs
int[] p = new int[] { i, j };

dfs(grid, p, visited, c);
}
}

return c;
}

private void dfs(char[][] grid, int[] p, int[][] visited, int c) {
int rows = grid.length;
int cols = grid[0].length;

int x = p[0];
int y = p[1];

// 标记为已访问
visited[x][y] = c;

int[][] points = new int[][] {
{ x, y - 1 }, { x - 1, y }, { x, y + 1 }, { x + 1, y }
};

for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (grid[x][y] == '0') {
// 无通路,跳过
continue;
}

if (visited[x][y] == 0) {
dfs(grid, q, visited, c);
}
}
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ '1', '1', '1', '1', '0' },

{ '1', '1', '0', '1', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '0', '0', '0' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = {
{ '1', '1', '0', '0', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '1', '0', '0' },

{ '0', '0', '0', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 3;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ '1', '1', '1' },
{ '0', '1', '0' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ '1', '1', '1' },
{ '1', '0', '1' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '0', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'0' },
{ '1', '0', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

解法3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
public class Solution {
public int numIslands(char[][] grid) {
if (grid.length == 0) {
return 0;
}

int c = 0;

int rows = grid.length;
int cols = grid[0].length;

int[][] visited = new int[rows][cols];

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '0') {
continue;
}

if (visited[i][j] > 0) {
continue;
}

// 新岛屿的左上角,计算新岛屿的标号
c++;

// 然后用图的遍历搜索属于当前岛屿的陆地
// dfs

dfs(grid, i, j, visited, c);
}
}

return c;
}

private void dfs(char[][] grid, int x, int y, int[][] visited, int c) {
int rows = grid.length;
int cols = grid[0].length;

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
return;
}

if (grid[x][y] == '0') {
// 无通路,跳过
return;
}

if (visited[x][y] == 0) {
// 标记为已访问
visited[x][y] = c;

dfs(grid, x, y - 1, visited, c);
dfs(grid, x - 1, y, visited, c);
dfs(grid, x, y + 1, visited, c);
dfs(grid, x + 1, y, visited, c);
}
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ '1', '1', '1', '1', '0' },

{ '1', '1', '0', '1', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '0', '0', '0' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = {
{ '1', '1', '0', '0', '0' },

{ '1', '1', '0', '0', '0' },

{ '0', '0', '1', '0', '0' },

{ '0', '0', '0', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 3;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ '1', '1', '1' },
{ '0', '1', '0' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ '1', '1', '1' },
{ '1', '0', '1' },
{ '1', '1', '1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '0', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'0' },
{ '1', '0', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1',
'1' },
{ '1', '0', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0',
'0' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' },
{ '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1' }
};

int result = new Solution().numIslands(grid);
int expect = 1;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

被围绕的区域

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。


示例 1:

输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
示例 2:

输入:board = [["X"]]
输出:[["X"]]


提示:

m == board.length
n == board[i].length
1 <= m, n <= 200
board[i][j] 为 'X' 或 'O'

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

public class Solution {
public void solve(char[][] board) {
if (board.length == 0) {
return;
}

int rows = board.length;
int cols = board[0].length;

Map<Integer, Map<Integer, Integer>> visited = new HashMap<>();

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 'X') {
continue;
}

if (visited.computeIfAbsent(i, k -> new HashMap<>()).containsKey(j)) {
// 有出路,跳过
continue;
}

boolean hasOut = false;

List<int[]> trail = new LinkedList<>();

Queue<int[]> queue = new LinkedList<>();

int[] p = new int[] { i, j };
int x = p[0];
int y = p[1];

queue.offer(p);

// 标记为已访问
visited.computeIfAbsent(x, k -> new HashMap<>()).put(y, null);
trail.add(p);

while (!queue.isEmpty()) {
p = queue.poll();
x = p[0];
y = p[1];

// 找到出路了
if (!hasOut) {
if (x == 0 || x == rows - 1 || y == 0 || y == cols - 1) {
hasOut = true;
}
}

int[][] points = new int[][] {
{ x, y - 1 }, { x - 1, y }, { x, y + 1 }, { x + 1, y }
};

for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (board[x][y] == 'X') {
// 无通路,跳过
continue;
}

if (!visited.computeIfAbsent(x, k -> new HashMap<>()).containsKey(y)) {
queue.offer(q);

// 标记为已访问
visited.computeIfAbsent(x, k -> new HashMap<>()).put(y, null);
trail.add(q);
}
}
}

if (!hasOut) {
for (int[] point : trail) {
board[point[0]][point[1]] = 'X';
}
}
}
}
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = { { 'X' } };

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = { { 'X' } };

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Solution {
public void solve(char[][] board) {
if (board.length == 0) {
return;
}

int rows = board.length;
int cols = board[0].length;

Map<Integer, Map<Integer, Integer>> visited = new HashMap<>();

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 'X') {
continue;
}

if (visited.computeIfAbsent(i, k -> new HashMap<>()).containsKey(j)) {
// 有出路,跳过
continue;
}

boolean hasOut = false;

List<int[]> trail = new LinkedList<>();

Deque<int[]> stack = new LinkedList<>();

int[] p = new int[] { i, j };
int x = p[0];
int y = p[1];

// 标记为已访问
visited.computeIfAbsent(x, k -> new HashMap<>()).put(y, null);
trail.add(p);

while (p != null || !stack.isEmpty()) {
if (p != null) {
x = p[0];
y = p[1];

// 找到出路了
if (!hasOut) {
if (x == 0 || x == rows - 1 || y == 0 || y == cols - 1) {
hasOut = true;
}
}

int[][] points = new int[][] {
{ x, y - 1 }, { x - 1, y }, { x, y + 1 }, { x + 1, y }
};

int[] r = null;
for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (board[x][y] == 'X') {
// 无通路,跳过
continue;
}

if (!visited.computeIfAbsent(x, k -> new HashMap<>()).containsKey(y)) {
r = q;

// 标记为已访问
visited.computeIfAbsent(x, k -> new HashMap<>()).put(y, null);
trail.add(q);

break;
}
}

if (r != null) {
stack.push(p); // 保存回退点

p = r; // 前进
} else {
// p = stack.isEmpty() ? null : stack.pop(); // 回溯
p = null; // 在下一次循环时跳转到回溯分支
}
} else {
p = stack.pop(); // 回溯
}
}

if (!hasOut) {
for (int[] point : trail) {
board[point[0]][point[1]] = 'X';
}
}
}
}
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = { { 'X' } };

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = { { 'X' } };

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

解法2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Solution {
public void solve(char[][] board) {
if (board.length == 0) {
return;
}

int rows = board.length;
int cols = board[0].length;

Map<Integer, Map<Integer, Integer>> visited = new HashMap<>();

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 'X') {
continue;
}

if (visited.computeIfAbsent(i, k -> new HashMap<>()).containsKey(j)) {
// 有出路,跳过
continue;
}

int[] p = new int[] { i, j };

List<int[]> trail = new LinkedList<>();

boolean hasOut = dfs(board, p, visited, trail);

if (!hasOut) {
for (int[] point : trail) {
board[point[0]][point[1]] = 'X';
}
}
}
}
}

private boolean dfs(char[][] board, int[] p, Map<Integer, Map<Integer, Integer>> visited, List<int[]> trail) {
int rows = board.length;
int cols = board[0].length;

boolean hasOut = false;

int x = p[0];
int y = p[1];

// 标记为已访问
visited.computeIfAbsent(x, k -> new HashMap<>()).put(y, null);
trail.add(p);

// 找到出路了
if (!hasOut) {
if (x == 0 || x == rows - 1 || y == 0 || y == cols - 1) {
hasOut = true;
}
}

int[][] points = new int[][] {
{ x, y - 1 }, { x - 1, y }, { x, y + 1 }, { x + 1, y }
};

for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (board[x][y] == 'X') {
// 无通路,跳过
continue;
}

if (!visited.computeIfAbsent(x, k -> new HashMap<>()).containsKey(y)) {
// 注意:dfs调用应该放在左边,放在右边的话可能会被hasOut短路而无法执行
// hasOut = hasOut || dfs(board, q, visited, trail);
hasOut = dfs(board, q, visited, trail) || hasOut;
}
}

return hasOut;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = { { 'X' } };

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = { { 'X' } };

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

解法3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Solution {
public void solve(char[][] board) {
if (board.length == 0) {
return;
}

int rows = board.length;
int cols = board[0].length;

Map<Integer, Map<Integer, Integer>> visited = new HashMap<>();

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 'X') {
continue;
}

if (visited.computeIfAbsent(i, k -> new HashMap<>()).containsKey(j)) {
// 有出路,跳过
continue;
}

List<int[]> trail = new LinkedList<>();

boolean hasOut = dfs(board, i, j, visited, trail);

if (!hasOut) {
for (int[] point : trail) {
board[point[0]][point[1]] = 'X';
}
}
}
}
}

private boolean dfs(char[][] board, int x, int y, Map<Integer, Map<Integer, Integer>> visited, List<int[]> trail) {
int rows = board.length;
int cols = board[0].length;

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
return false;
}

if (board[x][y] == 'X') {
// 无通路,跳过
return false;
}

boolean hasOut = false;

// 找到出路了
if (!hasOut) {
if (x == 0 || x == rows - 1 || y == 0 || y == cols - 1) {
hasOut = true;
}
}

if (!visited.computeIfAbsent(x, k -> new HashMap<>()).containsKey(y)) {
// 标记为已访问
visited.computeIfAbsent(x, k -> new HashMap<>()).put(y, null);
trail.add(new int[] { x, y });

// 注意:dfs调用应该放在左边,放在右边的话可能会被hasOut短路而无法执行
// hasOut = hasOut || dfs(board, q, visited, trail);
hasOut = dfs(board, x, y - 1, visited, trail) || hasOut;
hasOut = dfs(board, x - 1, y, visited, trail) || hasOut;
hasOut = dfs(board, x, y + 1, visited, trail) || hasOut;
hasOut = dfs(board, x + 1, y, visited, trail) || hasOut;
}

return hasOut;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
char[][] grid = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
char[][] grid = { { 'X' } };

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = { { 'X' } };

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
char[][] grid = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'X' },
{ 'O', 'O', 'O', 'O', 'O', 'O', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'X' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'O' },
{ 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'O', 'O', 'O' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'X', 'X' }
};

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
char[][] grid = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'O', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

new Solution().solve(grid);
char[][] result = grid;
char[][] expect = {
{ 'X', 'X', 'X', 'X', 'O', 'O', 'X', 'X', 'O' },
{ 'O', 'O', 'O', 'O', 'X', 'X', 'O', 'O', 'X' },
{ 'X', 'O', 'X', 'O', 'O', 'X', 'X', 'O', 'X' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'O', 'O', 'O' },
{ 'X', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'O' },
{ 'O', 'O', 'X', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'X', 'O', 'X', 'X', 'X' },
{ 'O', 'O', 'O', 'X', 'O', 'O', 'O', 'X', 'O' },
{ 'O', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O' }
};

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

克隆图

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

class Node {
public int val;
public List<Node> neighbors;
}


测试用例格式:

简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。

邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。

给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。



示例 1:

输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]
解释:
图中有 4 个节点。
节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
示例 2:

输入:adjList = [[]]
输出:[[]]
解释:输入包含一个空列表。该图仅仅只有一个值为 1 的节点,它没有任何邻居。
示例 3:

输入:adjList = []
输出:[]
解释:这个图是空的,它不含任何节点。
示例 4:

输入:adjList = [[2],[1]]
输出:[[2],[1]]


提示:

节点数不超过 100 。
每个节点值 Node.val 都是唯一的,1 <= Node.val <= 100。
无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
由于图是无向的,如果节点 p 是节点 q 的邻居,那么节点 q 也必须是节点 p 的邻居。
图是连通图,你可以从给定节点访问到所有节点。

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

public class Solution {
public Node cloneGraph(Node node) {
if (node == null) {
return null;
}

Set<Node> visited = new HashSet<>();
Map<Node, Node> caches = new HashMap<>();
Queue<Node> queue = new LinkedList<>();

caches.put(node, new Node(node.val));
queue.offer(node);
visited.add(node);

while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Node curNode = queue.poll();
Node newNode = caches.get(curNode);

for (Node neighbor : curNode.neighbors) {
if (!visited.contains(neighbor)) {
queue.offer(neighbor);
visited.add(neighbor);
}

Node newNeighbor = caches.get(neighbor);
if (newNeighbor == null) {
newNeighbor = new Node(neighbor.val);
caches.put(neighbor, newNeighbor);
}

newNode.neighbors.add(newNeighbor);
}
}
}

return caches.get(node);
}

static class Node {
public int val;
public java.util.List<Node> neighbors;

public Node(int val) {
this.val = val;
this.neighbors = new java.util.ArrayList<Node>();
}

public static Node genGraph(int[][] adjList) {
if (adjList.length == 0) {
return null;
}

java.util.Map<Integer, Node> map = new java.util.HashMap<>();
java.util.List<Node> list = new java.util.ArrayList<>();

int v;

for (int i = 0; i < adjList.length; i++) {
v = i + 1;

Node node = map.get(v);
if (node == null) {
node = new Node(v);
map.put(v, node);
}

list.add(node);

int[] array = adjList[i];

for (int j = 0; j < array.length; j++) {
v = array[j];

Node neighbor = map.get(v);
if (neighbor == null) {
neighbor = new Node(v);
map.put(v, neighbor);
}

node.neighbors.add(neighbor);
}
}

return list.get(0);
}

public static void printNode(Node node) {
if (node == null) {
System.out.println(node);

return;
}

java.util.List<String> list = new java.util.ArrayList<>();

java.util.Set<Node> visited = new java.util.HashSet<>();
java.util.Queue<Node> queue = new java.util.LinkedList<>();

queue.offer(node);
visited.add(node);

while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Node curNode = queue.poll();

java.util.List<String> tmp = new java.util.ArrayList<>();

for (Node neighbor : curNode.neighbors) {
if (!visited.contains(neighbor)) {
queue.offer(neighbor);
visited.add(neighbor);
}

String s = String.format("%2s@%25s", neighbor.val, neighbor);
tmp.add(s);
}

list.add("[" + String.join(",", tmp) + "]");
}
}

System.out.println("[" + String.join(",", list) + "]");
}

public static void printResult(Node node, Node result) {
System.out.println("--->");
Node.printNode(node);
System.out.println();
Node.printNode(result);
System.out.println("<---");
}
}

public static void main(String[] args) {
testCase1();
testCase2();
testCase3();
}

public static void testCase1() {
int[][] adjList = {
{ 2, 4 },
{ 1, 3 },
{ 2, 4 },
{ 1, 3 }
};

Node node = Node.genGraph(adjList);
Node result = new Solution().cloneGraph(node);

Node.printResult(node, result);
}

public static void testCase2() {
int[][] adjList = { {} };

Node node = Node.genGraph(adjList);
Node result = new Solution().cloneGraph(node);

Node.printResult(node, result);
}

public static void testCase3() {
int[][] adjList = {};

Node node = Node.genGraph(adjList);
Node result = new Solution().cloneGraph(node);

Node.printResult(node, result);
}
}

除法求值

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi = values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。

另有一些以数组 queries 表示的问题,其中 queries[j] = [Cj, Dj] 表示第 j 个问题,请你根据已知条件找出 Cj / Dj = ? 的结果作为答案。

返回 所有问题的答案 。如果存在某个无法确定的答案,则用 -1.0 替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用 -1.0 替代这个答案。

注意:输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。

注意:未在等式列表中出现的变量是未定义的,因此无法确定它们的答案。



示例 1:

输入:equations = [["a","b"],["b","c"]], values = [2.0,3.0], queries = [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]]
输出:[6.00000,0.50000,-1.00000,1.00000,-1.00000]
解释:
条件:a / b = 2.0, b / c = 3.0
问题:a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
结果:[6.0, 0.5, -1.0, 1.0, -1.0 ]
注意:x 是未定义的 => -1.0
示例 2:

输入:equations = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]]
输出:[3.75000,0.40000,5.00000,0.20000]
示例 3:

输入:equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]]
输出:[0.50000,2.00000,-1.00000,-1.00000]


提示:

1 <= equations.length <= 20
equations[i].length == 2
1 <= Ai.length, Bi.length <= 5
values.length == equations.length
0.0 < values[i] <= 20.0
1 <= queries.length <= 20
queries[i].length == 2
1 <= Cj.length, Dj.length <= 5
Ai, Bi, Cj, Dj 由小写英文字母与数字组成

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Solution {
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
Map<String, Map<String, Double>> graph = new HashMap<>();

for (int i = 0; i < equations.size(); i++) {
List<String> equation = equations.get(i);
Double value = values[i];

String s1 = equation.get(0);
String s2 = equation.get(1);

graph.computeIfAbsent(s1, s -> new HashMap<>()).put(s2, value);
graph.computeIfAbsent(s2, s -> new HashMap<>()).put(s1, 1 / value);
}

double[] array = new double[queries.size()];
for (int i = 0; i < array.length; i++) {
List<String> query = queries.get(i);

String x = query.get(0);
String y = query.get(1);

if (!graph.containsKey(x) || !graph.containsKey(y)) {
array[i] = -1.0d;
} else if (x.equals(y)) {
array[i] = 1.0d;
} else {
Set<String> visited = new HashSet<>();
Deque<String> stack = new LinkedList<>();

String p = x;

// 标记为已访问
visited.add(p);

while (p != null || !stack.isEmpty()) {
if (p != null) {
// 找到除数了
if (p.equals(y)) {
stack.push(p);

break;
}

String r = null;
for (String q : graph.get(p).keySet()) {
if (!visited.contains(q)) {
r = q;

// 标记为已访问
visited.add(q);

break;
}
}

if (r != null) {
stack.push(p); // 保存回退点

p = r; // 前进
} else {
// p = stack.isEmpty() ? null : stack.pop(); // 回溯
p = null; // 在下一次循环时跳转到回溯分支
}
} else {
p = stack.pop(); // 回溯
}
}

if (p != null || !stack.isEmpty()) {
// List<String> path = new LinkedList<>();
// while (!stack.isEmpty()) {
// path.add(0, stack.pop());
// }

// double value = 1.0d;
// for (int j = 0; j < path.size() - 1; j++) {
// String s1 = path.get(j);
// String s2 = path.get(j + 1);

// value = value * graph.get(s1).get(s2);
// }

double value = 1.0d;
String s2 = stack.pop();
while (!stack.isEmpty()) {
String s1 = stack.pop();

value = value * graph.get(s1).get(s2);

s2 = s1;
}

array[i] = value;
} else {
array[i] = -1.0d;
}
}
}

return array;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
String[][] equations = {
{ "a", "b" },
{ "b", "c" }
};
double[] values = { 2.0, 3.0 };
String[][] queries = {
{ "a", "c" },
{ "b", "a" },
{ "a", "e" },
{ "a", "a" },
{ "x", "x" }
};

double[] result = new Solution().calcEquation(TestUtils.toLists(equations), values,
TestUtils.toLists(queries));
double[] expect = { 6.00000, 0.50000, -1.00000, 1.00000, -1.00000 };

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
String[][] equations = {
{ "a", "b" },
{ "b", "c" },
{ "bc", "cd" }
};
double[] values = { 1.5, 2.5, 5.0 };
String[][] queries = {
{ "a", "c" },
{ "c", "b" },
{ "bc", "cd" },
{ "cd", "bc" }
};

double[] result = new Solution().calcEquation(TestUtils.toLists(equations), values,
TestUtils.toLists(queries));
double[] expect = { 3.75000, 0.40000, 5.00000, 0.20000 };

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
String[][] equations = {
{ "a", "b" },
};
double[] values = { 0.5 };
String[][] queries = {
{ "a", "b" },
{ "b", "a" },
{ "a", "c" },
{ "x", "y" }
};

double[] result = new Solution().calcEquation(TestUtils.toLists(equations), values,
TestUtils.toLists(queries));
double[] expect = { 0.50000, 2.00000, -1.00000, -1.00000 };

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
String[][] equations = {
{ "a", "b" },
};
double[] values = { 0.5 };
String[][] queries = {
{ "a", "b" },
{ "b", "a" },
{ "a", "c" },
{ "c", "a" },
{ "x", "y" }
};

double[] result = new Solution().calcEquation(TestUtils.toLists(equations), values,
TestUtils.toLists(queries));
double[] expect = { 0.50000, 2.00000, -1.00000, -1.00000, -1.00000 };

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
String[][] equations = {
{ "x1", "x2" },
{ "x2", "x3" },
{ "x3", "x4" },
{ "x4", "x5" }
};
double[] values = { 3.0, 4.0, 5.0, 6.0 };
String[][] queries = {
{ "x1", "x5" },
{ "x5", "x2" },
{ "x2", "x4" },
{ "x2", "x2" },
{ "x2", "x9" },
{ "x9", "x9" }
};

double[] result = new Solution().calcEquation(TestUtils.toLists(equations), values,
TestUtils.toLists(queries));
double[] expect = { 360.0, 0.008333333333333333, 20.0, 1.0, -1.0, -1.0 };

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

判断图是否存在环路

题目描述

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

public class Solution {
public boolean hasCycle(int numVertexes, int[][] edges) {
List<List<Integer>> graph = new LinkedList<>();
for (int i = 0; i < numVertexes; i++) {
graph.add(new LinkedList<>());
}

for (int[] edge : edges) {
int i = edge[0];
int j = edge[1];

graph.get(i).add(j);
}

int[] visited = new int[numVertexes];

for (int v = 0; v < numVertexes; v++) {
if (visited[v] > 0) {
continue;
}

Deque<Integer> stack = new LinkedList<>();

Integer p = v;

// 标记为访问中
visited[p] = 1;

while (p != null || !stack.isEmpty()) {
if (p != null) {
Integer r = null;
for (Integer q : graph.get(p)) {
if (visited[q] == 0) {
r = q;

// 标记为访问中
visited[q] = 1;

break;
} else if (visited[q] == 1) {
// 下一步是访问中的点,说明遇到环路了
return true;
}
}

if (r == null) {
// 标记为已访问
visited[p] = 2;
}

if (r != null) {
stack.push(p); // 保存回退点

p = r; // 前进
} else {
// p = stack.isEmpty() ? null : stack.pop(); // 回溯
p = null; // 在下一次循环时跳转到回溯分支
}
} else {
p = stack.pop(); // 回溯
}
}
}

return false;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int numVertexes = 2;
int[][] edges = { { 0, 1 }, { 1, 0 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = false;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 0 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 1 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 2 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
int numVertexes = 7;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 6, 4 }, { 6, 5 }, { 4, 3 }, { 5, 3 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = false;

return TestUtils.check(result, expect);
}

public static boolean testCase7() {
int numVertexes = 7;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 4, 6 }, { 6, 5 }, { 3, 4 }, { 5, 3 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase8() {
int numVertexes = 7;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 6, 4 }, { 5, 6 }, { 4, 3 }, { 3, 5 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase9() {
int numVertexes = 2;
int[][] edges = { { 0, 1 }, { 0, 0 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Solution {
public boolean hasCycle(int numVertexes, int[][] edges) {
List<List<Integer>> graph = new LinkedList<>();
for (int i = 0; i < numVertexes; i++) {
graph.add(new LinkedList<>());
}

for (int[] edge : edges) {
int i = edge[0];
int j = edge[1];

graph.get(i).add(j);
}

int[] indegs = new int[numVertexes];
for (int i = 0; i < graph.size(); i++) {
for (int j : graph.get(i)) {
indegs[j]++;
}
}

Queue<Integer> trail = new LinkedList<>();

Queue<Integer> queue = new LinkedList<>();

// 将所有入度为0的结点放入队列中
for (int v = 0; v < numVertexes; v++) {
if (indegs[v] == 0) {
queue.offer(v);
}
}

while (!queue.isEmpty()) {
Integer p = queue.poll();

trail.offer(p);

for (Integer q : graph.get(p)) {
indegs[q]--;

if (indegs[q] == 0) {
queue.offer(q);
}
}
}

if (trail.size() != numVertexes) {
return true;
}

return false;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int numVertexes = 2;
int[][] edges = { { 0, 1 }, { 1, 0 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = false;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 0 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 1 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int numVertexes = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 2 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
int numVertexes = 7;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 6, 4 }, { 6, 5 }, { 4, 3 }, { 5, 3 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = false;

return TestUtils.check(result, expect);
}

public static boolean testCase7() {
int numVertexes = 7;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 4, 6 }, { 6, 5 }, { 3, 4 }, { 5, 3 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase8() {
int numVertexes = 7;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, { 6, 4 }, { 5, 6 }, { 4, 3 }, { 3, 5 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase9() {
int numVertexes = 2;
int[][] edges = { { 0, 1 }, { 0, 0 } };

boolean result = new Solution().hasCycle(numVertexes, edges);
boolean expect = true;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

课程表

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。

例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。



示例 1:

输入:numCourses = 2, prerequisites = [[1, 0]]
输出:true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:

输入:numCourses = 2, prerequisites = [[1, 0], [0, 1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。


提示:

1 <= numCourses <= 2000
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i] 中的所有课程对 互不相同

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

public class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new LinkedList<>());
}

for (int[] prerequisite : prerequisites) {
int i = prerequisite[0];
int j = prerequisite[1];

graph.get(j).add(i);
}

int[] visited = new int[numCourses];

for (int course = 0; course < numCourses; course++) {
if (visited[course] > 0) {
continue;
}

Deque<Integer> stack = new LinkedList<>();

Integer p = course;

// 标记为访问中
visited[p] = 1;

while (p != null || !stack.isEmpty()) {
if (p != null) {
Integer r = null;
for (Integer q : graph.get(p)) {
if (visited[q] == 0) {
r = q;

// 标记为访问中
visited[q] = 1;

break;
} else if (visited[q] == 1) {
// 下一步是访问中的点,说明遇到环路了
return false;
}
}

if (r == null) {
// 标记为已访问
visited[p] = 2;
}

if (r != null) {
stack.push(p); // 保存回退点

p = r; // 前进
} else {
// p = stack.isEmpty() ? null : stack.pop(); // 回溯
p = null; // 在下一次循环时跳转到回溯分支
}
} else {
p = stack.pop(); // 回溯
}
}
}

return true;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int numCourses = 2;
int[][] prerequisites = { { 1, 0 } };

boolean result = new Solution().canFinish(numCourses, prerequisites);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int numCourses = 2;
int[][] prerequisites = { { 1, 0 }, { 0, 1 } };

boolean result = new Solution().canFinish(numCourses, prerequisites);
boolean expect = false;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int numCourses = 3;
int[][] prerequisites = { { 1, 0 }, { 1, 2 }, { 0, 1 } };

boolean result = new Solution().canFinish(numCourses, prerequisites);
boolean expect = false;

return TestUtils.check(result, expect);
}

}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new LinkedList<>());
}

int[] indegs = new int[numCourses];

for (int[] prerequisite : prerequisites) {
int i = prerequisite[0];
int j = prerequisite[1];

graph.get(j).add(i);

indegs[i]++;
}

Queue<Integer> path = new LinkedList<>();

Queue<Integer> queue = new LinkedList<>();

// 将所有入度为0的结点放入队列中
for (int course = 0; course < numCourses; course++) {
if (indegs[course] == 0) {
queue.offer(course);
}
}

while (!queue.isEmpty()) {
Integer p = queue.poll();

path.offer(p);

for (Integer q : graph.get(p)) {
indegs[q]--;

if (indegs[q] == 0) {
queue.offer(q);
}
}
}

if (path.size() != numCourses) {
return false;
}

return true;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int numCourses = 2;
int[][] prerequisites = { { 1, 0 } };

boolean result = new Solution().canFinish(numCourses, prerequisites);
boolean expect = true;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int numCourses = 2;
int[][] prerequisites = { { 1, 0 }, { 0, 1 } };

boolean result = new Solution().canFinish(numCourses, prerequisites);
boolean expect = false;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int numCourses = 3;
int[][] prerequisites = { { 1, 0 }, { 1, 2 }, { 0, 1 } };

boolean result = new Solution().canFinish(numCourses, prerequisites);
boolean expect = false;

return TestUtils.check(result, expect);
}

}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

课程表II

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。

例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。
返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。



示例 1:

输入:numCourses = 2, prerequisites = [[1,0]]
输出:[0,1]
解释:总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。
示例 2:

输入:numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
输出:[0,2,1,3]
解释:总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 。
示例 3:

输入:numCourses = 1, prerequisites = []
输出:[0]


提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= numCourses * (numCourses - 1)
prerequisites[i].length == 2
0 <= ai, bi < numCourses
ai != bi
所有[ai, bi] 互不相同

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

public class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new LinkedList<>());
}

for (int[] prerequisite : prerequisites) {
int i = prerequisite[0];
int j = prerequisite[1];

graph.get(j).add(i);
}

Deque<Integer> path = new LinkedList<>();

int[] visited = new int[numCourses];

for (int course = 0; course < numCourses; course++) {
if (visited[course] > 0) {
continue;
}

Deque<Integer> stack = new LinkedList<>();

Integer p = course;

// 标记为访问中
visited[p] = 1;

while (p != null || !stack.isEmpty()) {
if (p != null) {

Integer r = null;
for (Integer q : graph.get(p)) {
if (visited[q] == 0) {
r = q;

// 标记为访问中
visited[q] = 1;

break;
} else if (visited[q] == 1) {
// 下一步是访问中的点,说明遇到环路了
return new int[0];
}
}

if (r == null) {
// 标记为已访问
visited[p] = 2;

path.push(p);
}

if (r != null) {
stack.push(p); // 保存回退点

p = r; // 前进
} else {
// p = stack.isEmpty() ? null : stack.pop(); // 回溯
p = null; // 在下一次循环时跳转到回溯分支
}
} else {
p = stack.pop(); // 回溯
}
}
}

int[] array = new int[numCourses];
int i = 0;

while (!path.isEmpty()) {
array[i++] = path.pop();
}

return array;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int numCourses = 2;
int[][] prerequisites = { { 1, 0 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = { 0, 1 };

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int numCourses = 2;
int[][] prerequisites = { { 0, 1 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = { 1, 0 };

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int numCourses = 2;
int[][] prerequisites = {};

int[] result = new Solution().findOrder(numCourses, prerequisites);
// int[] expect = { 0, 1 };
int[] expect = { 1, 0 };

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int numCourses = 4;
int[][] prerequisites = { { 1, 0 }, { 2, 0 }, { 3, 1 }, { 3, 2 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
// int[] expect = { 0, 1, 2, 3 };
int[] expect = { 0, 2, 1, 3 };

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int numCourses = 4;
int[][] prerequisites = { { 1, 0 }, { 2, 0 }, { 0, 2 }, { 0, 1 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = {};

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
int numCourses = 3;
int[][] prerequisites = { { 2, 0 }, { 2, 1 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
// int[] expect = { 0, 1, 2 };
int[] expect = { 1, 0, 2 };

return TestUtils.check(result, expect);
}

}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new LinkedList<>());
}

int[] indegs = new int[numCourses];

for (int[] prerequisite : prerequisites) {
int i = prerequisite[0];
int j = prerequisite[1];

graph.get(j).add(i);

indegs[i]++;
}

Queue<Integer> path = new LinkedList<>();

Queue<Integer> queue = new LinkedList<>();

// 将所有入度为0的结点放入队列中
for (int course = 0; course < numCourses; course++) {
if (indegs[course] == 0) {
queue.offer(course);
}
}

while (!queue.isEmpty()) {
Integer p = queue.poll();

path.offer(p);

for (Integer q : graph.get(p)) {
indegs[q]--;

if (indegs[q] == 0) {
queue.offer(q);
}
}
}

if (path.size() != numCourses) {
return new int[0];
}

int[] array = new int[numCourses];
int i = 0;

while (!path.isEmpty()) {
array[i++] = path.poll();
}

return array;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int numCourses = 2;
int[][] prerequisites = { { 1, 0 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = { 0, 1 };

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int numCourses = 2;
int[][] prerequisites = { { 0, 1 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = { 1, 0 };

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int numCourses = 2;
int[][] prerequisites = {};

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = { 0, 1 };
// int[] expect = { 1, 0 };

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int numCourses = 4;
int[][] prerequisites = { { 1, 0 }, { 2, 0 }, { 3, 1 }, { 3, 2 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = { 0, 1, 2, 3 };
// int[] expect = { 0, 2, 1, 3 };

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int numCourses = 4;
int[][] prerequisites = { { 1, 0 }, { 2, 0 }, { 0, 2 }, { 0, 1 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = {};

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
int numCourses = 3;
int[][] prerequisites = { { 2, 0 }, { 2, 1 } };

int[] result = new Solution().findOrder(numCourses, prerequisites);
int[] expect = { 0, 1, 2 };
// int[] expect = { 1, 0, 2 };

return TestUtils.check(result, expect);
}

}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

蛇梯棋

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
给你一个大小为 n x n 的整数矩阵 board ,方格按从 1 到 n2 编号,编号遵循 转行交替方式 ,从左下角开始 (即,从 board[n - 1][0] 开始)每一行交替方向。

玩家从棋盘上的方格 1 (总是在最后一行、第一列)开始出发。

每一回合,玩家需要从当前方格 curr 开始出发,按下述要求前进:

选定目标方格 next ,目标方格的编号符合范围 [curr + 1, min(curr + 6, n2)] 。
该选择模拟了掷 六面体骰子 的情景,无论棋盘大小如何,玩家最多只能有 6 个目的地。
传送玩家:如果目标方格 next 处存在蛇或梯子,那么玩家会传送到蛇或梯子的目的地。否则,玩家传送到目标方格 next 。
当玩家到达编号 n2 的方格时,游戏结束。
r 行 c 列的棋盘,按前述方法编号,棋盘格中可能存在 “蛇” 或 “梯子”;如果 board[r][c] != -1,那个蛇或梯子的目的地将会是 board[r][c]。编号为 1 和 n2 的方格上没有蛇或梯子。

注意,玩家在每回合的前进过程中最多只能爬过蛇或梯子一次:就算目的地是另一条蛇或梯子的起点,玩家也 不能 继续移动。

举个例子,假设棋盘是 [[-1,4],[-1,3]] ,第一次移动,玩家的目标方格是 2 。那么这个玩家将会顺着梯子到达方格 3 ,但 不能 顺着方格 3 上的梯子前往方格 4 。
返回达到编号为 n2 的方格所需的最少移动次数,如果不可能,则返回 -1。



示例 1:

输入:board = [[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,35,-1,-1,13,-1],[-1,-1,-1,-1,-1,-1],[-1,15,-1,-1,-1,-1]]
输出:4
解释:
首先,从方格 1 [第 5 行,第 0 列] 开始。
先决定移动到方格 2 ,并必须爬过梯子移动到到方格 15 。
然后决定移动到方格 17 [第 3 行,第 4 列],必须爬过蛇到方格 13 。
接着决定移动到方格 14 ,且必须通过梯子移动到方格 35 。
最后决定移动到方格 36 , 游戏结束。
可以证明需要至少 4 次移动才能到达最后一个方格,所以答案是 4 。
示例 2:

输入:board = [[-1,-1],[-1,3]]
输出:1


提示:

n == board.length == board[i].length
2 <= n <= 20
grid[i][j] 的值是 -1 或在范围 [1, n2] 内
编号为 1 和 n2 的方格上没有蛇或梯子

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
import java.util.LinkedList;
import java.util.Queue;

public class Solution {
public int snakesAndLadders(int[][] board) {
if (board.length == 0) {
return 0;
}

int rows = board.length;
int cols = board[0].length;

int count = rows * cols;

// 存储关联的传送点
// 多用一个空间来省去值和下标的转换
int[] jumps = new int[count + 1];

// 存储到达某个点时需要移动的最少次数
// 多用一个空间来省去值和下标的转换
int[] steps = new int[count + 1];

int v = 1;
boolean reversed = false;
for (int i = rows - 1; i >= 0; i--) {
if (!reversed) {
for (int j = 0; j < cols; j++) {
jumps[v++] = board[i][j];
}
} else {
for (int j = cols - 1; j >= 0; j--) {
jumps[v++] = board[i][j];
}
}

reversed = !reversed;
}

boolean[] visited = new boolean[count + 1];

int p = 1;

Queue<Integer> queue = new LinkedList<>();

queue.offer(p);

// 标记为已访问
visited[p] = true;

while (!queue.isEmpty()) {
p = queue.poll();

int step = steps[p];

int b = p + 1;
int e = p + 6;
if (e > count) {
e = count;
}

for (int q = b; q <= e; q++) {
int r;
if (jumps[q] == -1) {
r = q;
} else {
r = jumps[q];
}

if (!visited[r]) {
queue.offer(r);

// 标记为已访问
visited[r] = true;
}

// 更新到达当前点的最少移动次数
if (steps[r] == 0 || steps[r] > step + 1) {
steps[r] = step + 1;
}
}
}

return steps[count] > 0 ? steps[count] : -1;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] board = {
{ -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1 },
{ -1, 35, -1, -1, 13, -1 },
{ -1, -1, -1, -1, -1, -1 },
{ -1, 15, -1, -1, -1, -1 }
};

int result = new Solution().snakesAndLadders(board);
int expect = 4;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] board = {
{ -1, -1 },
{ -1, 3 }
};

int result = new Solution().snakesAndLadders(board);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int[][] board = {
{ -1, -1, -1 },
{ -1, 9, -1 },
{ -1, -1, -1 }
};

int result = new Solution().snakesAndLadders(board);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int[][] board = {
{ -1, 4, -1 },
{ 6, 2, 6 },
{ -1, 3, -1 }
};

int result = new Solution().snakesAndLadders(board);
int expect = 2;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int[][] board = {
{ 1, 1, -1 },
{ 1, 1, 1 },
{ -1, 1, 1 }
};

int result = new Solution().snakesAndLadders(board);
int expect = -1;

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
int[][] board = {
{ -1, -1, 30, 14, 15, -1 },
{ 23, 9, -1, -1, -1, 9 },
{ 12, 5, 7, 24, -1, 30 },
{ 10, -1, -1, -1, 25, 17 },
{ 32, -1, 28, -1, -1, 32 },
{ -1, -1, 23, -1, 13, 19 }
};

int result = new Solution().snakesAndLadders(board);
int expect = 2;

return TestUtils.check(result, expect);
}

public static boolean testCase7() {
int[][] board = {
{ -1, 1, 1, 1 },
{ -1, 7, 1, 1 },
{ 16, 1, 1, 1 },
{ -1, 1, 9, 1 }
};

int result = new Solution().snakesAndLadders(board);
int expect = 3;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

最小基因变化

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是 'A'、'C'、'G' 和 'T' 之一。

假设我们需要调查从基因序列 start 变为 end 所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。

例如,"AACCGGTT" --> "AACCGGTA" 就是一次基因变化。
另有一个基因库 bank 记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。(变化后的基因必须位于基因库 bank 中)

给你两个基因序列 start 和 end ,以及一个基因库 bank ,请你找出并返回能够使 start 变化为 end 所需的最少变化次数。如果无法完成此基因变化,返回 -1 。

注意:起始基因序列 start 默认是有效的,但是它并不一定会出现在基因库中。



示例 1:

输入:start = "AACCGGTT", end = "AACCGGTA", bank = ["AACCGGTA"]
输出:1
示例 2:

输入:start = "AACCGGTT", end = "AAACGGTA", bank = ["AACCGGTA","AACCGCTA","AAACGGTA"]
输出:2
示例 3:

输入:start = "AAAAACCC", end = "AACCCCCC", bank = ["AAAACCCC","AAACCCCC","AACCCCCC"]
输出:3


提示:

start.length == 8
end.length == 8
0 <= bank.length <= 10
bank[i].length == 8
start、end 和 bank[i] 仅由字符 ['A', 'C', 'G', 'T'] 组成

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

public class Solution {
public int minMutation(String startGene, String endGene, String[] bank) {
Map<String, Map<String, Integer>> graph = new HashMap<>();

for (int i = 0; i < bank.length; i++) {
int c = getDifferenceCharCount(startGene, bank[i]);
if (c == 1) {
graph.computeIfAbsent(startGene, k -> new HashMap<>()).put(bank[i], 1);
}

for (int j = i + 1; j < bank.length; j++) {
c = getDifferenceCharCount(bank[i], bank[j]);
if (c == 1) {
graph.computeIfAbsent(bank[i], k -> new HashMap<>()).put(bank[j], 1);
graph.computeIfAbsent(bank[j], k -> new HashMap<>()).put(bank[i], 1);
}
}
}

if (!graph.containsKey(startGene)) {
return -1;
}

Map<String, Integer> steps = new HashMap<>();

Set<String> visited = new HashSet<>();

String p = startGene;

Queue<String> queue = new LinkedList<>();

queue.offer(p);

// 标记为已访问
visited.add(p);

while (!queue.isEmpty()) {
p = queue.poll();

int step = steps.getOrDefault(p, 0);

for (String q : graph.computeIfAbsent(p, k -> new HashMap<>()).keySet()) {
if (!visited.contains(q)) {
queue.offer(q);

// 标记为已访问
visited.add(q);
}

// 更新到达当前点的最少移动次数
if (!steps.containsKey(q) || steps.get(q) > step + 1) {
steps.put(q, step + 1);
}
}
}

return steps.getOrDefault(endGene, -1);
}

private int getDifferenceCharCount(String s, String t) {
int c = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != t.charAt(i)) {
c++;
}
}

return c;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {
public static boolean testCase1() {
String start = "AACCGGTT";
String end = "AACCGGTA";
String[] bank = { "AACCGGTA" };

int result = new Solution().minMutation(start, end, bank);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
String start = "AACCGGTT";
String end = "AAACGGTA";
String[] bank = { "AACCGGTA", "AACCGCTA", "AAACGGTA" };

int result = new Solution().minMutation(start, end, bank);
int expect = 2;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
String start = "AAAAACCC";
String end = "AACCCCCC";
String[] bank = { "AAAACCCC", "AAACCCCC", "AACCCCCC" };

int result = new Solution().minMutation(start, end, bank);
int expect = 3;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

最小路径和

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。



示例 1:

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。
示例 2:

输入:grid = [[1,2,3],[4,5,6]]
输出:12


提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 200

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
import java.util.LinkedList;
import java.util.Queue;

public class Solution {
public int minPathSum(int[][] grid) {
if (grid.length == 0) {
return 0;
}

int rows = grid.length;
int cols = grid[0].length;

int[][] sums = new int[rows][cols];
sums[0][0] = grid[0][0];

boolean[][] visited = new boolean[rows][cols];

int[] p = { 0, 0 };
int x = p[0];
int y = p[1];

Queue<int[]> queue = new LinkedList<>();

queue.offer(p);

// 标记为已访问
visited[x][y] = true;

while (!queue.isEmpty()) {
p = queue.poll();
x = p[0];
y = p[1];

int sum = sums[x][y];

int[][] points = new int[][] {
{ x + 1, y }, { x, y + 1 }
};

for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (!visited[x][y]) {
queue.offer(q);

// 标记为已访问
visited[x][y] = true;
}

if (sums[x][y] == 0 || sums[x][y] > sum + grid[x][y]) {
sums[x][y] = sum + grid[x][y];
}
}
}

return sums[rows - 1][cols - 1];
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] grid = {
{ 1, 3, 1 },
{ 1, 5, 1 },
{ 4, 2, 1 }
};

int result = new Solution().minPathSum(grid);
int expect = 7;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] grid = {
{ 1, 2, 3 },
{ 4, 5, 6 }
};

int result = new Solution().minPathSum(grid);
int expect = 12;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

进阶解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
public class Solution {
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;

int[][] dp = new int[m][n];

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i == 0 && j == 0)
dp[i][j] = grid[i][j];
else if (i == 0)
dp[i][j] = dp[i][j - 1] + grid[i][j];
else if (j == 0)
dp[i][j] = dp[i - 1][j] + grid[i][j];
else
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}

return dp[m - 1][n - 1];
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] grid = {
{ 1, 3, 1 },
{ 1, 5, 1 },
{ 4, 2, 1 }
};

int result = new Solution().minPathSum(grid);
int expect = 7;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] grid = {
{ 1, 2, 3 },
{ 4, 5, 6 }
};

int result = new Solution().minPathSum(grid);
int expect = 12;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

最小体力消耗路径

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。

一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。

请你返回从左上角走到右下角的最小 体力消耗值 。



示例 1:

输入:heights = [[1,2,2],[3,8,2],[5,3,5]]
输出:2
解释:路径 [1,3,5,3,5] 连续格子的差值绝对值最大为 2 。
这条路径比路径 [1,2,2,2,5] 更优,因为另一条路径差值最大值为 3 。
示例 2:

输入:heights = [[1,2,3],[3,8,4],[5,3,5]]
输出:1
解释:路径 [1,2,3,4,5] 的相邻格子差值绝对值最大为 1 ,比路径 [1,3,5,3,5] 更优。
示例 3:

输入:heights = [[1,2,1,1,1],[1,2,1,2,1],[1,2,1,2,1],[1,2,1,2,1],[1,1,1,2,1]]
输出:0
解释:上图所示路径不需要消耗任何体力。


提示:

rows == heights.length
columns == heights[i].length
1 <= rows, columns <= 100
1 <= heights[i][j] <= 106

题目解答

1
//

TODO:最小体力消耗路径

二进制矩阵中的最短路径

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。

二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:

路径途经的所有单元格的值都是 0 。
路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。



示例 1:

输入:grid = [[0,1],[1,0]]
输出:2
示例 2:

输入:grid = [[0,0,0],[1,1,0],[1,1,0]]
输出:4
示例 3:

输入:grid = [[1,0,0],[1,1,0],[1,1,0]]
输出:-1


提示:

n == grid.length
n == grid[i].length
1 <= n <= 100
grid[i][j] 为 0 或 1

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
import java.util.LinkedList;
import java.util.Queue;

public class Solution {
public int shortestPathBinaryMatrix(int[][] grid) {
if (grid.length == 0) {
return 0;
}

if (grid[0][0] != 0) {
return -1;
}

int rows = grid.length;
int cols = grid[0].length;

int[][] steps = new int[rows][cols];
steps[0][0] = 1;

boolean[][] visited = new boolean[rows][cols];

int[] p = { 0, 0 };
int x = p[0];
int y = p[1];

Queue<int[]> queue = new LinkedList<>();

queue.offer(p);

// 标记为已访问
visited[x][y] = true;

while (!queue.isEmpty()) {
p = queue.poll();
x = p[0];
y = p[1];

int step = steps[x][y];

int[][] points = new int[][] {
{ x, y - 1 }, { x - 1, y }, { x, y + 1 }, { x + 1, y },
{ x - 1, y - 1 }, { x - 1, y + 1 }, { x + 1, y - 1 }, { x + 1, y + 1 }
};

for (int[] q : points) {
x = q[0];
y = q[1];

if (x < 0 || x >= rows || y < 0 || y >= cols) {
// 无效点,跳过
continue;
}

if (grid[x][y] == 1) {
// 无通路,跳过
continue;
}

if (!visited[x][y]) {
queue.offer(q);

// 标记为已访问
visited[x][y] = true;
}

if (steps[x][y] == 0 || steps[x][y] > step + 1) {
steps[x][y] = step + 1;
}
}
}

int step = steps[rows - 1][cols - 1];

return step > 0 ? step : -1;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] grid = {
{ 0, 0, 0 },
{ 1, 1, 0 },
{ 1, 1, 0 }
};

int result = new Solution().shortestPathBinaryMatrix(grid);
int expect = 4;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] grid = {
{ 1, 0, 0 },
{ 1, 1, 0 },
{ 1, 1, 0 }
};

int result = new Solution().shortestPathBinaryMatrix(grid);
int expect = -1;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

最短路径

核心思想:最短路径算法

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

有 n 个网络节点,标记为 1 到 n。

给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] = (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。

现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1 。



示例 1:

输入:times = [[2, 1, 1], [2, 3, 1], [3, 4, 1]], n = 4, k = 2
输出:2
示例 2:

输入:times = [[1, 2, 1]], n = 2, k = 1
输出:1
示例 3:

输入:times = [[1, 2, 1]], n = 2, k = 2
输出:-1


提示:

1 <= k <= n <= 100
1 <= times.length <= 6000
times[i].length == 3
1 <= ui, vi <= n
ui != vi
0 <= wi <= 100
所有 (ui, vi) 对都 互不相同(即,不含重复边)

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
public class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
int[][] graph = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
graph[i][j] = Integer.MAX_VALUE;
}
}

for (int[] time : times) {
int i = time[0] - 1;
int j = time[1] - 1;
int v = time[2];

graph[i][j] = v;
}

// Dijkstra

int[] dist = new int[n];
for (int i = 0; i < n; i++) {
dist[i] = Integer.MAX_VALUE;
}
dist[k - 1] = 0;

boolean[] used = new boolean[n];

while (true) {
int i = -1;
for (int j = 0; j < n; j++) {
if (!used[j] && (i == -1 || dist[j] < dist[i])) {
i = j;
}
}

if (i == -1) {
break;
} else {
used[i] = true;
}

for (int j = 0; j < n; j++) {
if (graph[i][j] == Integer.MAX_VALUE) {
// 无通路,跳过
continue;
}

// 更新从i到达j点时k到j的最短距离
if (dist[i] + graph[i][j] < dist[j]) {
dist[j] = dist[i] + graph[i][j];
}
}
}

int maxValue = Integer.MIN_VALUE;
for (int i = 0; i < dist.length; i++) {
int d = dist[i];

if (d == Integer.MAX_VALUE) {
// 当前点不可达
return -1;
} else if (d > maxValue) {
maxValue = d;
}
}

return maxValue;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] times = {
{ 2, 1, 1 },
{ 2, 3, 1 },
{ 3, 4, 1 }
};
int n = 4;
int k = 2;

int result = new Solution().networkDelayTime(times, n, k);
int expect = 2;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] times = {
{ 2, 1, 1 },
{ 2, 3, 1 },
{ 3, 4, 1 }
};
int n = 4;
int k = 3;

int result = new Solution().networkDelayTime(times, n, k);
int expect = -1;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int[][] times = {
{ 1, 2, 1 }
};
int n = 2;
int k = 1;

int result = new Solution().networkDelayTime(times, n, k);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int[][] times = {
{ 1, 2, 1 }
};
int n = 2;
int k = 2;

int result = new Solution().networkDelayTime(times, n, k);
int expect = -1;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int[][] times = {
{ 2, 7, 63 },
{ 4, 3, 60 },
{ 1, 3, 53 },
{ 5, 6, 100 },
{ 1, 4, 40 },
{ 4, 7, 95 },
{ 4, 6, 97 },
{ 3, 4, 68 },
{ 1, 7, 75 },
{ 2, 6, 84 },
{ 1, 6, 27 },
{ 5, 3, 25 },
{ 6, 2, 2 },
{ 3, 7, 57 },
{ 5, 4, 2 },
{ 7, 1, 53 },
{ 5, 7, 35 },
{ 4, 1, 60 },
{ 5, 2, 95 },
{ 3, 5, 28 },
{ 6, 1, 61 },
{ 2, 5, 28 }
};
int n = 7;
int k = 3;

int result = new Solution().networkDelayTime(times, n, k);
int expect = 119;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
public class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
int[][] graph = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
graph[i][j] = Integer.MAX_VALUE;
}
}

for (int[] time : times) {
int i = time[0] - 1;
int j = time[1] - 1;
int v = time[2];

graph[i][j] = v;
}

// Floyd

int[][] dists = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
dists[i][j] = 0;
} else {
dists[i][j] = graph[i][j];
}
}
}

for (int t = 0; t < n; t++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (dists[i][t] == Integer.MAX_VALUE || dists[t][j] == Integer.MAX_VALUE) {
// 无通路,跳过
continue;
}

if (dists[i][t] + dists[t][j] < dists[i][j]) {
dists[i][j] = dists[i][t] + dists[t][j];
}
}
}
}

int[] dist = dists[k - 1];
int maxValue = Integer.MIN_VALUE;
for (int i = 0; i < dist.length; i++) {
int d = dist[i];

if (d == Integer.MAX_VALUE) {
// 当前点不可达
return -1;
} else if (d > maxValue) {
maxValue = d;
}
}

return maxValue;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] times = {
{ 2, 1, 1 },
{ 2, 3, 1 },
{ 3, 4, 1 }
};
int n = 4;
int k = 2;

int result = new Solution().networkDelayTime(times, n, k);
int expect = 2;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] times = {
{ 2, 1, 1 },
{ 2, 3, 1 },
{ 3, 4, 1 }
};
int n = 4;
int k = 3;

int result = new Solution().networkDelayTime(times, n, k);
int expect = -1;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int[][] times = {
{ 1, 2, 1 }
};
int n = 2;
int k = 1;

int result = new Solution().networkDelayTime(times, n, k);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int[][] times = {
{ 1, 2, 1 }
};
int n = 2;
int k = 2;

int result = new Solution().networkDelayTime(times, n, k);
int expect = -1;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int[][] times = {
{ 2, 7, 63 },
{ 4, 3, 60 },
{ 1, 3, 53 },
{ 5, 6, 100 },
{ 1, 4, 40 },
{ 4, 7, 95 },
{ 4, 6, 97 },
{ 3, 4, 68 },
{ 1, 7, 75 },
{ 2, 6, 84 },
{ 1, 6, 27 },
{ 5, 3, 25 },
{ 6, 2, 2 },
{ 3, 7, 57 },
{ 5, 4, 2 },
{ 7, 1, 53 },
{ 5, 7, 35 },
{ 4, 1, 60 },
{ 5, 2, 95 },
{ 3, 5, 28 },
{ 6, 1, 61 },
{ 2, 5, 28 }
};
int n = 7;
int k = 3;

int result = new Solution().networkDelayTime(times, n, k);
int expect = 119;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

最小生成树

核心思想:最小生成树算法

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
给你一个points 数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi] 。

连接点 [xi, yi] 和点 [xj, yj] 的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj| ,其中 |val| 表示 val 的绝对值。

请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接。



示例 1:

输入:points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
输出:20
解释:

我们可以按照上图所示连接所有点得到最小总费用,总费用为 20 。
注意到任意两个点之间只有唯一一条路径互相到达。
示例 2:

输入:points = [[3,12],[-2,5],[-4,1]]
输出:18
示例 3:

输入:points = [[0,0],[1,1],[1,0],[-1,1]]
输出:4
示例 4:

输入:points = [[-1000000,-1000000],[1000000,1000000]]
输出:4000000
示例 5:

输入:points = [[0,0]]
输出:0


提示:

1 <= points.length <= 1000
-106 <= xi, yi <= 106
所有点 (xi, yi) 两两不同。

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
public class Solution {
public int minCostConnectPoints(int[][] points) {
int n = points.length;
int[][] graph = new int[n][n];

for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
graph[i][j] = Integer.MAX_VALUE;
} else {
graph[i][j] = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
}
}
}

// Prim

boolean[] used = new boolean[n];
int cnt = 0; // 计数(统计已选择了多少个点,总数为n个)

used[(int) (Math.random() * n)] = true; // 先选择一个(随机选一个都可以)
cnt++;

int cost = 0;
while (true) {
int min = Integer.MAX_VALUE;
int k = -1;

for (int i = 0; i < n; i++) {
if (!used[i]) {
continue;
}

for (int j = 0; j < n; j++) {
if (used[j]) {
continue;
}

if (graph[i][j] == Integer.MAX_VALUE) {
// 无通路,跳过
continue;
}

if (graph[i][j] < min) {
min = graph[i][j];
k = j;
}
}
}

if (k == -1) {
break;
}

cost = cost + min;
used[k] = true;

cnt++;
if (cnt == n) {
break;
}
}

if (cnt != n) {
// 存在某个点不可达
return -1;
}

return cost;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] points = { { 0, 0 }, { 2, 2 }, { 3, 10 }, { 5, 2 }, { 7, 0 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 20;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] points = { { 3, 12 }, { -2, 5 }, { -4, 1 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 18;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int[][] points = { { 0, 0 }, { 1, 1 }, { 1, 0 }, { -1, 1 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 4;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int[][] points = { { -1000000, -1000000 }, { 1000000, 1000000 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 4000000;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int[][] points = { { 0, 0 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 0;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
import java.util.Arrays;

public class Solution {
public int minCostConnectPoints(int[][] points) {
int n = points.length;
int[][] graph = new int[n][n];

for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
graph[i][j] = Integer.MAX_VALUE;
} else {
graph[i][j] = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
}
}
}

// Kruskal

int ec = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (graph[i][j] != Integer.MAX_VALUE) {
ec++;
}
}
}

int ei = 0;

int[][] edges = new int[ec][3];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (graph[i][j] != Integer.MAX_VALUE) {
edges[ei++] = new int[] {
i, j, graph[i][j]
};
}
}
}

Arrays.sort(edges, (o1, o2) -> o1[2] - o2[2]);

boolean[] used = new boolean[n];
int cnt = 0; // 计数(统计已选择了多少个边,总数为n - 1个)

int cost = 0;
for (int t = 0; t < edges.length; t++) {
int[] edge = edges[t];
int i = edge[0];
int j = edge[1];
int w = edge[2];

if (used[i] && used[j]) {
continue;
}

cost = cost + w;
used[i] = true;
used[j] = true;

cnt++;
if (cnt == n - 1) {
break;
}
}

if (cnt != n - 1) {
// 存在某个点不可达
return -1;
}

return cost;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] points = { { 0, 0 }, { 2, 2 }, { 3, 10 }, { 5, 2 }, { 7, 0 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 20;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[][] points = { { 3, 12 }, { -2, 5 }, { -4, 1 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 18;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int[][] points = { { 0, 0 }, { 1, 1 }, { 1, 0 }, { -1, 1 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 4;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int[][] points = { { -1000000, -1000000 }, { 1000000, 1000000 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 4000000;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int[][] points = { { 0, 0 } };

int result = new Solution().minCostConnectPoints(points);
int expect = 0;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

旅行商问题

核心思想:旅行商算法

题目描述

1
小明目前在做一份毕业旅行的规划。打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的花销。给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
public class Solution {
public int[] tps(int[][] graph) {
int n = graph.length;

boolean[] visited = new boolean[n];
int[] trail = new int[n];

int[] minCost = { Integer.MAX_VALUE };
int[] path = new int[n + 1];

backtrace(0, n, 0, graph, 0, visited, trail, 0, minCost, path);

return path;
}

/**
*
* @param i 步骤计数
* @param n 步骤总数
* @param u 步骤选项(顶点的序号)
* @param graph 原始数据(图数据)
* @param start 原始数据(起点)
* @param visited 访问状态
* @param trail 访问轨迹
* @param curCost 当前结果(到达当前顶点时的开销)
* @param minCost 最终结果(回到起点时的最小开销)
* @param path 结果路径(回到起点时的结果路径)
*/
private void backtrace(int i, int n, int u, int[][] graph, int start, boolean[] visited,
int[] trail, int curCost, int[] minCost, int[] path) {

// 当前开销已经比最小值大了,需要进行剪枝
if (curCost > minCost[0]) {
return;
}

if (i == n - 1) {
trail[i] = u;

curCost = curCost + graph[u][start];

// System.out.println("path: " + java.util.Arrays.toString(trail));
// System.out.println("val: " + curCost);

if (curCost < minCost[0]) {
minCost[0] = curCost;

for (int t = 0; t < trail.length; t++) {
path[t] = trail[t];
}
path[path.length - 1] = start;
}

return;
}

for (int v = 0; v < n; v++) {
if (graph[u][v] == 0) {
continue;
}

if (!visited[v]) {
trail[i] = u;

visited[u] = true;
backtrace(i + 1, n, v, graph, start, visited, trail, curCost + graph[u][v], minCost, path);
visited[u] = false; // 回溯时撤销选择
}
}
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[][] graph = {
{ 0, 2, 6, 5 },
{ 2, 0, 4, 4 },
{ 6, 4, 0, 2 },
{ 5, 4, 2, 0 }
};

int[] result = new Solution().tps(graph);
int[] expect = { 0, 1, 2, 3, 0 };

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

其他解法

解法1

1
//

TODO:旅行商问题(动态规划 + 状态压缩)

邮递员问题

题目描述

题目解答

TODO:邮递员问题

困难

网格中的最短路径

题目描述

1
2
3
给你一个 m * n 的网格,其中每个单元格不是 0(空)就是 1(障碍物)。每一步,您都可以在空白单元格中上、下、左、右移动。

如果您 最多 可以消除 k 个障碍物,请找出从左上角 (0, 0) 到右下角 (m-1, n-1) 的最短路径,并返回通过该路径所需的步数。如果找不到这样的路径,则返回 -1 。

题目解答

1
//

TODO:网格中的最短路径

访问所有节点的最短路径

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号。

给你一个数组 graph 表示这个图。其中,graph[i] 是一个列表,由所有与节点 i 直接相连的节点组成。

返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。



示例 1:

输入:graph = [[1, 2, 3], [0], [0], [0]]
输出:4
解释:一种可能的路径为 [1, 0, 2, 0, 3]
示例 2:

输入:graph = [[1], [0, 2, 4], [1, 3, 4], [2], [1, 2]]
输出:4
解释:一种可能的路径为 [0, 1, 4, 2, 3]


提示:

n == graph.length
1 <= n <= 12
0 <= graph[i].length < n
graph[i] 不包含 i
如果 graph[a] 包含 b ,那么 graph[b] 也包含 a
输入的图总是连通图

题目解答

1
//

TODO:访问所有节点的最短路径

单词接龙

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk:

每一对相邻的单词只差一个字母。
对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。
sk == endWord
给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。


示例 1:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:5
解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
示例 2:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:0
解释:endWord "cog" 不在字典中,所以无法进行转换。


提示:

1 <= beginWord.length <= 10
endWord.length == beginWord.length
1 <= wordList.length <= 5000
wordList[i].length == beginWord.length
beginWord、endWord 和 wordList[i] 由小写英文字母组成
beginWord != endWord
wordList 中的所有字符串 互不相同

题目解答

1
//

TODO:单词接龙

只想买包辣条