-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathTheMazeIII.java
98 lines (84 loc) · 3.5 KB
/
TheMazeIII.java
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
// https://leetcode.com/problems/the-maze-iii
// T: O(m * n log(m * n))
// S: O(m * n)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
public class TheMazeIII {
private record Info(int[] position, int distance, String path) {}
private record Position(int[] position, String direction) {}
private static final Position[] DIRECTIONS = new Position[] {
new Position(new int[] { 1, 0 }, "d"),
new Position(new int[] { 0, -1 }, "l"),
new Position(new int[] { 0, 1 }, "r"),
new Position(new int[] { -1, 0 }, "u")
};
// T: O(m * n * log(m * n)), S: O(m * n)
public String findShortestWay(int[][] maze, int[] ball, int[] hole) {
final int[][] distances = getDistances(maze.length, maze[0].length);
final Queue<Info> queue = new PriorityQueue<>((a, b) -> {
if (a.distance == b.distance) {
return a.path.compareTo(b.path);
}
return Integer.compare(a.distance, b.distance);
});
queue.add(new Info(ball, 0, ""));
String path = null;
while (!queue.isEmpty()) {
final Info info = queue.poll();
if (distances[info.position[0]][info.position[1]] <= info.distance) {
continue;
}
distances[info.position[0]][info.position[1]] = info.distance;
if (info.position[0] == hole[0] && info.position[1] == hole[1]) {
if (path == null) {
path = info.path;
} else {
path = path.compareTo(info.path) > 0 ? info.path : path;
}
}
for (Position position : validPositions(maze, info.position, hole)) {
queue.add(new Info(
position.position,
info.distance + manhattanDistance(position.position, info.position),
info.path + position.direction
));
}
}
final int minDistance = distances[hole[0]][hole[1]];
return minDistance == Integer.MAX_VALUE ? "impossible" : path;
}
// T: O(1), S:O(1)
private static int manhattanDistance(int[] p1, int[] p2) {
return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]);
}
// T: O(m + n), S: O(1)
private static List<Position> validPositions(int[][] grid, int[] position, int[] target) {
final List<Position> result = new ArrayList<>();
for (Position p : DIRECTIONS) {
int row = position[0], column = position[1];
while (row >= 0 && row < grid.length
&& column >= 0 && column < grid[0].length && grid[row][column] == 0 &&
(row != target[0] || column != target[1])) {
row += p.position[0];
column += p.position[1];
}
if (row == target[0] && column == target[1]) {
result.add(new Position(new int[] { row, column}, p.direction));
} else {
result.add(new Position(new int[]{row - p.position[0], column - p.position[1]}, p.direction));
}
}
return result;
}
// T: O(m * n), S: O(m * n)
private static int[][] getDistances(int rows, int columns) {
final int[][] distances = new int[rows][columns];
for (int[] row : distances) {
Arrays.fill(row, Integer.MAX_VALUE);
}
return distances;
}
}