题目链接

LeetCode

题目描述

示例 1:

130. 被围绕的区域** - 图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”]]
解释: 被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是 “相连” 的。

示例 2:

输入: board = [[“X”]]
输出: [[“X”]]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 200
  • board[i][j]'X''O'

    解题思路

    方法一:DFS

    本题给定的矩阵中有三种元素:

  • 字母 X

  • 被字母 X 包围的字母 O
  • 没有被字母 X 包围的字母 O

本题要求将所有被字母 X 包围的字母 O都变为字母 X ,但很难判断哪些 O 是被包围的,哪些 O 不是被包围的。

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

  • 对于每一个边界上的 O,我们以它为起点,标记所有与它直接或间接相连的字母 O
  • 最后我们遍历这个矩阵,对于每一个字母:

    • 如果该字母被标记过,则该字母为没有被字母 X 包围的字母 O,我们将其还原为字母 O
    • 如果该字母没有被标记过,则该字母为被字母 X 包围的字母 O,我们将其修改为字母 X
      1. class Solution {
      2. public void solve(char[][] board) {
      3. int n = board.length;
      4. if(n == 0){
      5. return;
      6. }
      7. // 左右边界向内遍历
      8. int m = board[0].length;
      9. for(int i = 0; i < n; ++i){
      10. dfs(board, i, 0);
      11. dfs(board, i, m - 1);
      12. }
      13. // 上下边界向内遍历
      14. for(int i = 0; i < m; ++i){
      15. dfs(board, 0, i);
      16. dfs(board, n - 1, i);
      17. }
      18. // 将剩余的 'O' 转换为 'X',将 'A'(与边界连接的'O') 转换为'O'
      19. for(int i = 0; i < n; ++i){
      20. for(int j = 0; j < m; ++j){
      21. if(board[i][j] == 'A'){
      22. board[i][j] = 'O';
      23. }else if(board[i][j] == 'O'){
      24. board[i][j] = 'X';
      25. }
      26. }
      27. }
      28. }
      29. // 深度优先遍历,与边界相连的 'O'字符用 'A' 表示
      30. private void dfs(char[][] board, int i, int j){
      31. if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != 'O'){
      32. return;
      33. }
      34. board[i][j] = 'A';
      35. dfs(board, i - 1, j);
      36. dfs(board, i + 1, j);
      37. dfs(board, i, j - 1);
      38. dfs(board, i, j + 1);
      39. }
      40. }
  • 时间复杂度 O(n * m)

  • 空间复杂度 O(n * m)

    方法二:BFS

  1. class Solution {
  2. int[] x = new int[]{-1, 1, 0, 0};
  3. int[] y = new int[]{0, 0, -1, 1};
  4. public void solve(char[][] board) {
  5. int n = board.length;
  6. if(n == 0){
  7. return;
  8. }
  9. Deque<int[]> q = new LinkedList<>();
  10. // 左右边界向内遍历
  11. int m = board[0].length;
  12. for(int i = 0; i < n; ++i){
  13. if(board[i][0] == 'O'){
  14. board[i][0] = 'A';
  15. q.offer(new int[]{i, 0});
  16. }
  17. if(board[i][m - 1] == 'O'){
  18. board[i][m - 1] = 'A';
  19. q.offer(new int[]{i, m - 1});
  20. }
  21. }
  22. // 上下边界向内遍历
  23. for(int i = 0; i < m; ++i){
  24. if(board[0][i] == 'O'){
  25. board[0][i] = 'A';
  26. q.offer(new int[]{0, i});
  27. }
  28. if(board[n - 1][i] == 'O'){
  29. board[n - 1][i] = 'A';
  30. q.offer(new int[]{n - 1, i});
  31. }
  32. }
  33. while(!q.isEmpty()){
  34. int[] tmp = q.poll();
  35. for(int i = 0; i < 4; ++i){
  36. if(tmp[0] + x[i] >= 0 && tmp[0] + x[i] < n && tmp[1] + y[i] >= 0 && tmp[1] + y[i] < m && board[tmp[0] + x[i]][tmp[1] + y[i]] == 'O'){
  37. board[tmp[0] + x[i]][tmp[1] + y[i]] = 'A';
  38. q.offer(new int[]{tmp[0] + x[i], tmp[1] + y[i]});
  39. }
  40. }
  41. }
  42. // 将剩余的 'O' 转换为 'X',将 'A'(与边界连接的'O') 转换为'O'
  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. }
  • 时间复杂度 O(n * m)
  • 空间复杂度 O(n * m)