BFS标记已经搜索过的格子避免重复搜索,一定一定要在入队时候就标记搜索
如果在出队时才标记搜索,那么下一层的节点可能会把上一层的重复入队,因为上一层前面的节点出队了,后面的还没出队因此还视为未被搜索,有重复入队的风险!
1.常规单源BFS解法:5ms 48.8 MB
| 12
 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
 
 | 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写法:
| 12
 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
 
 | 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
| 12
 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
 
 | 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
参考: ʚ自在飞花ɞ | 多个源点的广搜
| 12
 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
 
 | 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
| 12
 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
 
 | 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
| 12
 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
 
 | 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;
 }
 }
 
 |