130. 被围绕的区域
      
        给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' 组成,捕获 所有 被围绕的区域:
- 连接:一个单元格与水平或垂直方向上相邻的单元格连接
 
- 区域:连接所有 
'O' 的单元格来形成一个区域 
- 围绕:如果您可以用 
'X' 单元格 连接这个区域,并且区域中没有任何单元格位于 board 边缘,则该区域被 'X' 单元格围绕 
通过将输入矩阵 board 中的所有 'O' 替换为 'X' 来 捕获被围绕的区域
示例 1
输入:board = [[“X”,”X”,”X”,”X”],[“X”,”O”,”O”,”X”],[“X”,”X”,”O”,”X”],[“X”,”O”,”X”,”X”]]
输出:[[“X”,”X”,”X”,”X”],[“X”,”X”,”X”,”X”],[“X”,”X”,”X”,”X”],[“X”,”O”,”X”,”X”]]
解释:

在上图中,底部的区域没有被捕获,因为它在 board 的边缘并且不能被围绕
示例 2
输入:board = [[“X”]]
输出:[[“X”]]
Solution 1
第一次尝试,使用深度优先搜索
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 99 100 101
   | class Solution {     public void solve(char[][] board) {         List<O> oList = new ArrayList<>();         Map<Integer, Map<Integer, O>> oMap = new HashMap<>();         O o;         for (int i = 0; i < board.length; i++) {             boolean topOrBottom = i == 0 || i == board.length - 1;             for (int j = 0, k = board[i].length; j < k; j++) {                 if (board[i][j] != 'O') {                     continue;                 }                 o = new O(i, j);                 if (topOrBottom || j == 0 || j == k - 1) {                     o.isBoard = true;                 }                 oList.add(o);                 Map<Integer, O> jMap = oMap.computeIfAbsent(i, k1 -> new HashMap<>());                 jMap.put(j, o);             }         }
          Set<O> traveled = new HashSet<>();         for (O val : oList) {             if (val.isBoard && !traveled.contains(val)) {                 traveled.add(val);                 odfs(val, traveled, oMap);             }         }
          for (int i = 0; i < board.length; i++) {             for (int j = 0, k = board[i].length; j < k; j++) {                 char c = board[i][j];                 if (c == 'O' && !oMap.get(i).get(j).isBoard) {                     board[i][j] = 'X';                 }             }         }     }
      private void odfs(O boardO, Set<O> traveled, Map<Integer, Map<Integer, O>> oMap) {         int x = boardO.getX();         int y = boardO.getY();         Map<Integer, O> x_s_1 = oMap.get(x - 1);         if (x_s_1 != null && x_s_1.get(y) != null && !traveled.contains(x_s_1.get(y))) {             O o = x_s_1.get(y);             o.isBoard = true;             traveled.add(o);             odfs(o, traveled, oMap);         }         Map<Integer, O> x_p_1 = oMap.get(x + 1);         if (x_p_1 != null && x_p_1.get(y) != null && !traveled.contains(x_p_1.get(y))) {             O o = x_p_1.get(y);             o.isBoard = true;             traveled.add(o);             odfs(o, traveled, oMap);         }         O o_s_1 = oMap.get(x).get(y - 1);         if (o_s_1 != null && !traveled.contains(o_s_1)) {             o_s_1.isBoard = true;             traveled.add(o_s_1);             odfs(o_s_1, traveled, oMap);         }         O o_p_1 = oMap.get(x).get(y + 1);         if (o_p_1 != null && !traveled.contains(o_p_1)) {             o_p_1.isBoard = true;             traveled.add(o_p_1);             odfs(o_p_1, traveled, oMap);         }     }
      private static class O {         private int x;         private int y;         private boolean isBoard = false;
          public O(int x, int y) {             this.x = x;             this.y = y;         }
          public int getX() {             return x;         }
          public int getY() {             return y;         }
          @Override         public boolean equals(Object o) {             if (this == o) return true;             if (o == null || getClass() != o.getClass()) return false;             return x == ((O) o).getX() && y == ((O) o).getY();         }
          @Override         public int hashCode() {             return Objects.hash(x, y);         }     } }
  | 
 
- 执行用时:14 ms(击败 5.10% 使用 Java 的用户)
 
- 内存消耗:45.14 MB(击败 10.36% 使用 Java 的用户)
 
Solution 2
核心逻辑不变,省略路径的记录,将遍历过的路径用特殊字符标记
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
   | class Solution {     int xSize;     int ySize;     public void solve(char[][] board) {         xSize = board.length;         if (xSize == 0) {             return;         }         ySize = board[0].length;
          for (int i = 0; i < xSize; i++) {             dfs(board, i, 0);             dfs(board, i, ySize - 1);         }
          for (int i = 1; i < ySize - 1; i++) {             dfs(board, 0, i);             dfs(board, xSize - 1, i);         }
          for (int i = 0; i < xSize; i++) {             for (int j = 0; j < ySize; j++) {                 if (board[i][j] == 'A') {                     board[i][j] = 'O';                 } else if (board[i][j] == 'O') {                     board[i][j] = 'X';                 }             }         }     }
      private void dfs(char[][] board, int x, int y) {         if (x < 0 || x >= xSize || y < 0 || y >= ySize || board[x][y] != 'O') {             return;         }         board[x][y] = 'A';         dfs(board, x - 1, y);         dfs(board, x + 1, y);         dfs(board, x, y - 1);         dfs(board, x, y + 1);     } }
  | 
 
Source
130. 被围绕的区域