BFS标记已经搜索过的格子避免重复搜索,一定一定要在入队时候就标记搜索
如果在出队时才标记搜索,那么下一层的节点可能会把上一层的重复入队,因为上一层前面的节点出队了,后面的还没出队因此还视为未被搜索,有重复入队的风险!
1.常规单源BFS解法:5ms 48.8 MB
class Solution { boolean[][] canReach; int[][] grid; int m, n; int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int numEnclaves(int[][] _grid) {
grid = _grid; m = grid.length; n = grid[0].length; canReach = new boolean[m][n]; for (int i = 0; i < m; i++) { if (grid[i][0] == 1) bfs(i, 0); if (grid[i][n - 1] == 1) bfs(i, n - 1); } for (int j = 1; j < n - 1; j++) { if (grid[0][j] == 1) bfs(0, j); if (grid[m - 1][j] == 1) bfs(m - 1, j); } int res = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1 && !canReach[i][j]) res++; } } return res; }
private void bfs(int i, int j) { if (canReach[i][j]) return; Queue<int[]> que = new LinkedList<>(); canReach[i][j] = true; que.add(new int[]{i, j}); while (!que.isEmpty()) { int size = que.size(); while (size-- > 0) { int[] poll = que.poll(); int x = poll[0], y = poll[1]; for (int[] dir : dirs) { int newX = x + dir[0], newY = y + dir[1]; if (newX >= 0 && newX <= m - 1 && newY >= 0 && newY <= n - 1 && grid[newX][newY] == 1 && !canReach[newX][newY]) { canReach[newX][newY] = true; que.add(new int[]{newX, newY}); } } } } } }
|
2.多源BFS写法:
class Solution { boolean[][] canReach;
public int numEnclaves(int[][] grid) {
int m = grid.length, n = grid[0].length; int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; Queue<int[]> que = new LinkedList<>(); for (int i = 0; i < m; i++) { if (grid[i][0] == 1) { grid[i][0] = 2; que.add(new int[]{i, 0}); } if (grid[i][n - 1] == 1) { grid[i][n - 1] = 2; que.add(new int[]{i, n - 1}); } } for (int j = 1; j < n - 1; j++) { if (grid[0][j] == 1) { grid[0][j] = 2; que.add(new int[]{0, j}); } if (grid[m - 1][j] == 1) { grid[m - 1][j] = 2; que.add(new int[]{m - 1, j}); } } while (!que.isEmpty()) { int size = que.size(); while (size-- > 0) { int[] poll = que.poll(); int x = poll[0], y = poll[1]; for (int[] dir : dirs) { int newX = x + dir[0], newY = y + dir[1]; if (newX >= 0 && newX <= m - 1 && newY >= 0 && newY <= n - 1 && grid[newX][newY] == 1) { grid[newX][newY] = 2; que.add(new int[]{newX, newY}); } } } } int res = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1) res++; } } return res; } }
|
3.DFS解法:4ms 48.7 MB
class Solution { boolean[][] canReach; int[][] grid; int m, n; int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int numEnclaves(int[][] _grid) {
grid = _grid; m = grid.length; n = grid[0].length; canReach = new boolean[m][n]; for (int i = 0; i < m; i++) { if (grid[i][0] == 1) dfs(i, 0); if (grid[i][n - 1] == 1) dfs(i, n - 1); } for (int j = 1; j < n - 1; j++) { if (grid[0][j] == 1) dfs(0, j); if (grid[m - 1][j] == 1) dfs(m - 1, j); } int res = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1 && !canReach[i][j]) res++; } } return res; }
private void dfs(int i, int j) { if (canReach[i][j]) return; canReach[i][j] = true; for (int[] dir : dirs) { int newI = i + dir[0], newJ = j + dir[1]; if (newI >= 0 && newI <= m - 1 && newJ >= 0 && newJ <= n - 1 && grid[newI][newJ] == 1) { dfs(newI, newJ); } } } }
|
多源BFS实际就是单源BFS的第二层,在前面加上一个超级源点指向最初入队的节点,就是普通的单源BFS
参考: ʚ自在飞花ɞ | 多个源点的广搜
class Solution { public int maxDistance(int[][] grid) {
int m = grid.length, n = grid[0].length; int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; Queue<int[]> que = new LinkedList<>(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1) { que.add(new int[]{i, j}); } } } if (que.size() == m * n || que.size() == 0) return -1; int dis = -1; while (!que.isEmpty()) { int size = que.size(); while (size-- > 0) { int[] poll = que.poll(); int x = poll[0], y = poll[1]; for (int[] dir : dirs) { int newX = x + dir[0], newY = y + dir[1]; if (newX >= 0 && newX <= m - 1 && newY >= 0 && newY <= n - 1 && grid[newX][newY] == 0) { grid[newX][newY] = 2; que.add(new int[]{newX, newY}); } } } dis++; } return dis; } }
|
在矩阵中,关于BFS入队的类型,可以为int[] 类型的[x,y],也可以将其化为int类型后面再进行解析
1.常规写法:44 ms 136.9 MB
class Solution { public int[][] highestPeak(int[][] isWater) {
int m = isWater.length, n = isWater[0].length; int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; Queue<int[]> que = new LinkedList<>(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (isWater[i][j] == 1) { isWater[i][j] = 0; que.add(new int[]{i, j}); } else { isWater[i][j] = -1; } } } while (!que.isEmpty()) { int size = que.size(); while (size-- > 0) { int[] poll = que.poll(); int x = poll[0], y = poll[1]; for (int[] dir : dirs) { int newX = x + dir[0], newY = y + dir[1]; if (newX >= 0 && newX <= m - 1 && newY >= 0 && newY <= n - 1 && isWater[newX][newY] == -1) { isWater[newX][newY] = isWater[x][y] + 1; que.add(new int[]{newX, newY}); } } } } return isWater; } }
|
化为int类型后:45 ms 158.2 MB
class Solution { public int[][] highestPeak(int[][] isWater) { int m = isWater.length, n = isWater[0].length; int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; Queue<Integer> que = new LinkedList<>(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (isWater[i][j] == 1) { isWater[i][j] = 0; que.add(i * n + j); } else { isWater[i][j] = -1; } } } while (!que.isEmpty()) { int size = que.size(); while (size-- > 0) { int poll = que.poll(); int x = poll / n, y = poll % n; for (int[] dir : dirs) { int newX = x + dir[0], newY = y + dir[1]; if (newX >= 0 && newX <= m - 1 && newY >= 0 && newY <= n - 1 && isWater[newX][newY] == -1) { isWater[newX][newY] = isWater[x][y] + 1; que.add(newX * n + newY); } } } } return isWater; } }
|