|
| 1 | +package g2801_2900.s2812_find_the_safest_path_in_a_grid; |
| 2 | + |
| 3 | +// #Medium #Array #Binary_Search #Matrix #Union_Find #Breadth_First_Search |
| 4 | +// #2023_11_20_Time_57_ms_(100.00%)_Space_65.3_MB_(77.00%) |
| 5 | + |
| 6 | +import java.util.Arrays; |
| 7 | +import java.util.List; |
| 8 | + |
| 9 | +@SuppressWarnings("java:S6541") |
| 10 | +public class Solution { |
| 11 | + private static final int[][] MOVES = new int[][] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; |
| 12 | + |
| 13 | + public int maximumSafenessFactor(List<List<Integer>> grid) { |
| 14 | + final int yLen = grid.size(); |
| 15 | + final int xLen = grid.get(0).size(); |
| 16 | + if (grid.get(0).get(0) == 1 || grid.get(yLen - 1).get(xLen - 1) == 1) { |
| 17 | + return 0; |
| 18 | + } |
| 19 | + int[][] secure = new int[yLen][xLen]; |
| 20 | + int[] deque = new int[yLen * xLen]; |
| 21 | + int[] nDeque = new int[yLen * xLen]; |
| 22 | + int[] tmpDeque; |
| 23 | + int[] queue = new int[yLen * xLen]; |
| 24 | + int[] root = new int[yLen * xLen]; |
| 25 | + int head = -1; |
| 26 | + int tail = -1; |
| 27 | + int qIdx = -1; |
| 28 | + int end = yLen * xLen - 1; |
| 29 | + int curY; |
| 30 | + int curX; |
| 31 | + int nextY; |
| 32 | + int nextX; |
| 33 | + int curID; |
| 34 | + int nextID; |
| 35 | + for (int y = 0; y < yLen; y++) { |
| 36 | + Arrays.fill(secure[y], -1); |
| 37 | + for (int x = 0; x < xLen; x++) { |
| 38 | + if (grid.get(y).get(x) == 1) { |
| 39 | + secure[y][x] = 0; |
| 40 | + curID = y * xLen + x; |
| 41 | + root[curID] = queue[++qIdx] = nDeque[++tail] = curID; |
| 42 | + } |
| 43 | + } |
| 44 | + } |
| 45 | + int start = 0; |
| 46 | + int stop = qIdx; |
| 47 | + for (int t = 1; tail > -1; t++) { |
| 48 | + tmpDeque = deque; |
| 49 | + deque = nDeque; |
| 50 | + nDeque = tmpDeque; |
| 51 | + head = tail; |
| 52 | + tail = -1; |
| 53 | + start = qIdx; |
| 54 | + for (; head >= 0; head--) { |
| 55 | + curY = deque[head] / xLen; |
| 56 | + curX = deque[head] % xLen; |
| 57 | + for (int[] move : MOVES) { |
| 58 | + nextY = curY + move[0]; |
| 59 | + nextX = curX + move[1]; |
| 60 | + if (nextY >= 0 |
| 61 | + && nextY < yLen |
| 62 | + && nextX >= 0 |
| 63 | + && nextX < xLen |
| 64 | + && secure[nextY][nextX] < 0) { |
| 65 | + secure[nextY][nextX] = t; |
| 66 | + nextID = nextY * xLen + nextX; |
| 67 | + root[nextID] = queue[++qIdx] = nDeque[++tail] = nextID; |
| 68 | + } |
| 69 | + } |
| 70 | + } |
| 71 | + } |
| 72 | + for (qIdx = start; qIdx > stop; qIdx--) { |
| 73 | + curY = queue[qIdx] / xLen; |
| 74 | + curX = queue[qIdx] % xLen; |
| 75 | + curID = curY * xLen + curX; |
| 76 | + for (int[] move : MOVES) { |
| 77 | + nextY = curY + move[0]; |
| 78 | + nextX = curX + move[1]; |
| 79 | + if (nextY >= 0 |
| 80 | + && nextY < yLen |
| 81 | + && nextX >= 0 |
| 82 | + && nextX < xLen |
| 83 | + && secure[nextY][nextX] >= secure[curY][curX]) { |
| 84 | + nextID = nextY * xLen + nextX; |
| 85 | + root[find(root, curID)] = find(root, nextID); |
| 86 | + } |
| 87 | + } |
| 88 | + if (find(root, 0) == find(root, end)) { |
| 89 | + return secure[curY][curX]; |
| 90 | + } |
| 91 | + } |
| 92 | + return 0; |
| 93 | + } |
| 94 | + |
| 95 | + private int find(int[] root, int idx) { |
| 96 | + if (idx == root[idx]) { |
| 97 | + return idx; |
| 98 | + } |
| 99 | + root[idx] = find(root, root[idx]); |
| 100 | + return root[idx]; |
| 101 | + } |
| 102 | +} |
0 commit comments