题目

类型:BFS
难度:中等
image.png

解题思路

本题要求将所有被字母 X 包围的字母 O都变为字母 X ,但很难判断哪些 O 是被包围的,哪些 O 不是被包围的。
注意到题目解释中提到:任何边界上的 O 都不会被填充为 X。 我们可以想到,所有的不被包围的 O 都直接或间接与边界上的 O 相连。我们可以利用这个性质判断 O 是否在边界上,具体地说:

  • 对于每一个边界上的 O,我们以它为起点,标记所有与它直接或间接相连的字母 O;
  • 最后我们遍历这个矩阵,对于每一个字母:
    • 如果该字母被标记过,则该字母为没有被字母 X 包围的字母 O,我们将其还原为字母 O;
    • 如果该字母没有被标记过,则该字母为被字母 X 包围的字母 O,我们将其修改为字母 X。

      代码

  1. class Solution {
  2. int[] dx = {1, -1, 0, 0};
  3. int[] dy = {0, 0, 1, -1};
  4. public void solve(char[][] board) {
  5. int n = board.length;
  6. if (n == 0) {
  7. return;
  8. }
  9. int m = board[0].length;
  10. Queue<int[]> queue = new LinkedList<int[]>();
  11. for (int i = 0; i < n; i++) {
  12. if (board[i][0] == 'O') {
  13. queue.offer(new int[]{i, 0});
  14. board[i][0] = 'A';
  15. }
  16. if (board[i][m - 1] == 'O') {
  17. queue.offer(new int[]{i, m - 1});
  18. board[i][m - 1] = 'A';
  19. }
  20. }
  21. for (int i = 1; i < m - 1; i++) {
  22. if (board[0][i] == 'O') {
  23. queue.offer(new int[]{0, i});
  24. board[0][i] = 'A';
  25. }
  26. if (board[n - 1][i] == 'O') {
  27. queue.offer(new int[]{n - 1, i});
  28. board[n - 1][i] = 'A';
  29. }
  30. }
  31. while (!queue.isEmpty()) {
  32. int[] cell = queue.poll();
  33. int x = cell[0], y = cell[1];
  34. for (int i = 0; i < 4; i++) {
  35. int mx = x + dx[i], my = y + dy[i];
  36. if (mx < 0 || my < 0 || mx >= n || my >= m || board[mx][my] != 'O') {
  37. continue;
  38. }
  39. queue.offer(new int[]{mx, my});
  40. board[mx][my] = 'A';
  41. }
  42. }
  43. for (int i = 0; i < n; i++) {
  44. for (int j = 0; j < m; j++) {
  45. if (board[i][j] == 'A') {
  46. board[i][j] = 'O';
  47. } else if (board[i][j] == 'O') {
  48. board[i][j] = 'X';
  49. }
  50. }
  51. }
  52. }
  53. }