|
1 | 1 | package LeetCodeJava.BFS; |
2 | 2 |
|
3 | 3 | // https://leetcode.com/problems/shortest-path-in-binary-matrix/description/ |
| 4 | + |
| 5 | +import java.util.LinkedList; |
| 6 | +import java.util.Queue; |
| 7 | + |
4 | 8 | /** |
5 | 9 | * 1091. Shortest Path in Binary Matrix |
6 | 10 | * Medium |
|
44 | 48 | public class ShortestPathInBinaryMatrix { |
45 | 49 |
|
46 | 50 | // V0 |
| 51 | + // IDEA: BFS (fixed by gpt) |
| 52 | + public int shortestPathBinaryMatrix(int[][] grid) { |
| 53 | + int n = grid.length; |
| 54 | + |
| 55 | + // Edge case: Start or end point is blocked |
| 56 | + if (grid[0][0] != 0 || grid[n - 1][n - 1] != 0) { |
| 57 | + return -1; |
| 58 | + } |
| 59 | + |
| 60 | + // Directions for 8-connected neighbors |
| 61 | + int[][] directions = { |
| 62 | + { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }, |
| 63 | + { -1, -1 }, { -1, 1 }, { 1, 1 }, { 1, -1 } |
| 64 | + }; |
| 65 | + |
| 66 | + // BFS Queue |
| 67 | + Queue<int[]> queue = new LinkedList<>(); |
| 68 | + queue.offer(new int[] { 0, 0, 1 }); // {x, y, distance} |
| 69 | + |
| 70 | + // Visited set to avoid revisiting |
| 71 | + boolean[][] visited = new boolean[n][n]; |
| 72 | + visited[0][0] = true; |
| 73 | + |
| 74 | + while (!queue.isEmpty()) { |
| 75 | + int[] current = queue.poll(); |
| 76 | + int x = current[0]; |
| 77 | + int y = current[1]; |
| 78 | + int distance = current[2]; |
| 79 | + |
| 80 | + // Check if we reached the destination |
| 81 | + if (x == n - 1 && y == n - 1) { |
| 82 | + return distance; |
| 83 | + } |
| 84 | + |
| 85 | + // Explore all 8 neighbors |
| 86 | + for (int[] dir : directions) { |
| 87 | + int newX = x + dir[0]; |
| 88 | + int newY = y + dir[1]; |
| 89 | + |
| 90 | + // Check if the new position is valid |
| 91 | + if (newX >= 0 && newX < n && newY >= 0 && newY < n |
| 92 | + && grid[newX][newY] == 0 && !visited[newX][newY]) { |
| 93 | + queue.offer(new int[] { newX, newY, distance + 1 }); |
| 94 | + visited[newX][newY] = true; |
| 95 | + } |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + // If no path is found, return -1 |
| 100 | + return -1; |
| 101 | + } |
| 102 | + |
| 103 | + // V1 |
| 104 | + // https://leetcode.com/problems/shortest-path-in-binary-matrix/solutions/2043319/why-use-bfs-search-every-possible-path-v-aaov/ |
| 105 | + // IDEA: BFS |
| 106 | + public int shortestPathBinaryMatrix_1(int[][] grid) { |
| 107 | + if (grid == null || grid.length == 0 || grid[0].length == 0) { |
| 108 | + return -1; |
| 109 | + } |
| 110 | + |
| 111 | + int ans = 0; |
| 112 | + |
| 113 | + int row = grid.length; |
| 114 | + int col = grid[0].length; |
| 115 | + |
| 116 | + if (grid[0][0] == 1 || grid[row - 1][col - 1] == 1) { |
| 117 | + return -1; |
| 118 | + } |
| 119 | + |
| 120 | + int[][] dirs = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } }; |
| 121 | + |
| 122 | + boolean[][] visited = new boolean[row][col]; |
| 123 | + |
| 124 | + Queue<int[]> queue = new LinkedList<>(); |
| 125 | + queue.offer(new int[] { 0, 0 }); |
| 126 | + visited[0][0] = true; |
| 127 | + |
| 128 | + while (!queue.isEmpty()) { |
| 129 | + int size = queue.size(); |
| 130 | + ans++; |
| 131 | + |
| 132 | + for (int i = 0; i < size; i++) { |
| 133 | + int[] curPos = queue.poll(); |
| 134 | + |
| 135 | + if (curPos[0] == row - 1 && curPos[1] == col - 1) { |
| 136 | + return ans; |
| 137 | + } |
| 138 | + |
| 139 | + for (int[] dir : dirs) { |
| 140 | + int nextX = curPos[0] + dir[0]; |
| 141 | + int nextY = curPos[1] + dir[1]; |
| 142 | + |
| 143 | + if (nextX < 0 || nextX >= row || nextY < 0 || nextY >= col || visited[nextX][nextY] |
| 144 | + || grid[nextX][nextY] == 1) { |
| 145 | + continue; |
| 146 | + } |
| 147 | + |
| 148 | + visited[nextX][nextY] = true; |
| 149 | + queue.offer(new int[] { nextX, nextY }); |
| 150 | + } |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + return -1; |
| 155 | + } |
| 156 | + |
| 157 | + // V2 |
| 158 | + // IDEA: BFS |
| 159 | + // https://leetcode.com/problems/shortest-path-in-binary-matrix/solutions/1541087/easy-and-clear-java-bfs-solution-with-ex-yeqm/ |
| 160 | + public int shortestPathBinaryMatrix_2(int[][] grid) { |
| 161 | + |
| 162 | + // initialization for 8 directions, a map(map is the name, it is a Queue for |
| 163 | + // BFS) and row-column boundaries |
| 164 | + int[][] dir = { { 1, 1 }, { 1, 0 }, { 0, 1 }, { 1, -1 }, { -1, 1 }, { -1, 0 }, { 0, -1 }, { -1, -1 } }; |
| 165 | + Queue<int[]> map = new LinkedList<>(); |
| 166 | + int rMax = grid.length; |
| 167 | + int cMax = grid[0].length; |
| 168 | + |
| 169 | + // if start point is blocked, return -1, otherwise give map the start point |
| 170 | + if (grid[0][0] == 1) |
| 171 | + return -1; |
| 172 | + |
| 173 | + // first two parameters are coordinates, third keep track of the distance |
| 174 | + map.offer(new int[] { 0, 0, 1 }); |
| 175 | + |
| 176 | + while (!map.isEmpty()) { |
| 177 | + // get current coordinates and distance travelled |
| 178 | + int[] location = map.poll(); |
| 179 | + int r = location[0]; |
| 180 | + int c = location[1]; |
| 181 | + int distance = location[2]; |
| 182 | + |
| 183 | + // return if reaches the destination |
| 184 | + if (r == rMax - 1 && c == cMax - 1) |
| 185 | + return distance; |
| 186 | + |
| 187 | + // search 8 directions for unexplored points around current point |
| 188 | + for (int[] d : dir) { |
| 189 | + int r2 = r + d[0]; |
| 190 | + int c2 = c + d[1]; |
| 191 | + if (r2 < rMax && r2 >= 0 && c2 < cMax && c2 >= 0 && grid[r2][c2] == 0) { |
| 192 | + // add unexplored point to map and increment distance by 1 |
| 193 | + map.offer(new int[] { r2, c2, distance + 1 }); |
| 194 | + // set this point to 1 as explored |
| 195 | + grid[r2][c2] = 1; |
| 196 | + } |
| 197 | + } |
| 198 | + } |
| 199 | + // whole space searched, cannot reach destination |
| 200 | + return -1; |
| 201 | + } |
| 202 | + |
| 203 | + // V3 |
| 204 | + // IDEA: BFS |
| 205 | + // https://leetcode.com/problems/shortest-path-in-binary-matrix/solutions/3584016/java-bfs-beats-70-18-lines-clean-code-by-w3hy/ |
47 | 206 | // public int shortestPathBinaryMatrix(int[][] grid) { |
| 207 | +// if (grid[0][0] == 1) |
| 208 | +// return -1; |
| 209 | +// |
| 210 | +// var moves = new int[][] { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, |
| 211 | +// { 1, 1 } }; |
| 212 | +// var n = grid.length; |
| 213 | +// var seen = new boolean[n][n]; |
| 214 | +// var queue = new ArrayDeque<int[]>(); |
| 215 | +// queue.offer(new int[] { 0, 0 }); |
| 216 | +// |
| 217 | +// for (var cnt = 1; !queue.isEmpty(); cnt++) { |
| 218 | +// for (var i = queue.size(); i > 0; i--) { |
| 219 | +// var cell = queue.poll(); |
| 220 | +// |
| 221 | +// if (cell[0] == n - 1 && cell[1] == n - 1) |
| 222 | +// return cnt; |
48 | 223 | // |
| 224 | +// for (var move : moves) { |
| 225 | +// var x = cell[0] + move[0]; |
| 226 | +// var y = cell[1] + move[1]; |
| 227 | +// |
| 228 | +// if (x >= 0 && x < n && y >= 0 && y < n && !seen[x][y] && grid[x][y] == 0) { |
| 229 | +// seen[x][y] = true; |
| 230 | +// queue.offer(new int[] { x, y }); |
| 231 | +// } |
| 232 | +// } |
| 233 | +// } |
| 234 | +// } |
| 235 | +// return -1; |
49 | 236 | // } |
50 | 237 |
|
51 | | - // V1 |
52 | | - |
53 | | - // V2 |
| 238 | + // V4 |
| 239 | + // IDEA: DFS |
| 240 | + // https://leetcode.com/problems/shortest-path-in-binary-matrix/solutions/313937/posting-my-java-dfs-solution-54ms-to-dem-hi3l/ |
| 241 | + // Transfer the dist value at (r,c) to or from neighbor cells. |
| 242 | + // Whenever a cell has a updated (smaller) dist value, a recursive call of |
| 243 | + // grow() will be done on behalf of it. |
| 244 | + private void grow(int[][] grid, int[][] dist, int r, int c) { |
| 245 | + int m = grid.length, n = grid[0].length; |
| 246 | + int d0 = dist[r][c]; |
| 247 | + for (int i = -1; i <= 1; i++) { |
| 248 | + for (int j = -1; j <= 1; j++) { |
| 249 | + if (i == 0 && j == 0) |
| 250 | + continue; |
| 251 | + int x = r + i; |
| 252 | + int y = c + j; |
| 253 | + if (x >= 0 && x < m && y >= 0 && y < n) { |
| 254 | + if (grid[x][y] == 1) |
| 255 | + continue; |
| 256 | + int d1 = dist[x][y]; |
| 257 | + if (d1 < d0 - 1) { // get a smaller value from a neighbor; then re-start the process. |
| 258 | + dist[r][c] = d1 + 1; |
| 259 | + grow(grid, dist, r, c); // TODO some optimization to avoid stack overflow |
| 260 | + return; |
| 261 | + } else if (d1 > d0 + 1) { // give a smaller value to a neighbor |
| 262 | + dist[x][y] = d0 + 1; |
| 263 | + grow(grid, dist, x, y); |
| 264 | + } |
| 265 | + } |
| 266 | + } |
| 267 | + } |
| 268 | + } |
| 269 | + |
| 270 | + public int shortestPathBinaryMatrix_4(int[][] grid) { |
| 271 | + int m = grid.length, n = grid[0].length; |
| 272 | + int[][] dist = new int[m][n]; // dist[i][j]: distance of the cell (i,j) to (0,0) |
| 273 | + for (int i = 0; i < m; i++) { |
| 274 | + for (int j = 0; j < n; j++) { |
| 275 | + dist[i][j] = Integer.MAX_VALUE; |
| 276 | + } |
| 277 | + } |
| 278 | + dist[0][0] = 1; |
| 279 | + if (grid[0][0] == 1 || grid[m - 1][n - 1] == 1) |
| 280 | + return -1; |
| 281 | + grow(grid, dist, 0, 0); |
| 282 | + return (dist[m - 1][n - 1] != Integer.MAX_VALUE ? dist[m - 1][n - 1] : -1); |
| 283 | + } |
| 284 | + |
54 | 285 | } |
0 commit comments