• 130. Surrounded Regions


    问题:

    给定一个m*n棋盘,由O和X填入。

    将棋盘中被X包围的O转化成X。

    说明:在四周边缘的O,以及和这些O相邻(上下左右相邻)的O,无法转化。其他的棋盘内部O皆可转化为X。

    Example 1:
    Input: board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
    Output: [["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
    Explanation: Surrounded regions should not be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. Two cells are connected if they are adjacent cells connected horizontally or vertically.
    
    Example 2:
    Input: board = [["X"]]
    Output: [["X"]]
     
    Constraints:
    m == board.length
    n == board[i].length
    1 <= m, n <= 200
    board[i][j] is 'X' or 'O'.
    

      

    解法:BFS, Disjoint Set(并查集)

    解法一:BFS

    queue:保存当前一层遍历中,遇到的O。(从四边缘开始,每相邻一层,为新的一层)

    对当前格子:无法转化的对象:将board上标记为 $

    若相邻为O 且 该格子没有访问过,则,q.push({i, j})

    最后遍历board,若标记为$,则填入O,其他的O填入X。

    代码参考:

     1 class Solution {
     2 public:
     3     bool isValid(int i, int j, int m, int n) {
     4         if(i<0 || j<0 || i>=m || j>=n) return false;
     5         return true;
     6     }
     7     void solve(vector<vector<char>>& board) {
     8         int m = board.size(), n = board[0].size();
     9         vector<vector<bool>> visited(m,vector<bool>(n,0));
    10         queue<vector<int>> q;
    11         vector<vector<int>> dir = {{1,0},{-1,0},{0,1},{0,-1}};
    12         for(int i=0; i<m; i++) {
    13             if(board[i][0] == 'O') {
    14                 q.push({i, 0});
    15                 visited[i][0] = 1;
    16             }
    17             if(board[i][n-1] == 'O') {
    18                 q.push({i, n-1});
    19                 visited[i][n-1] = 1;
    20             }
    21         }
    22         for(int j=0; j<n; j++) {
    23             if(board[0][j] == 'O') {
    24                 q.push({0, j});
    25                 visited[0][j] = 1;
    26             }
    27             if(board[m-1][j] == 'O') {
    28                 q.push({m-1, j});
    29                 visited[m-1][j] = 1;
    30             }
    31         }
    32         while(!q.empty()) {
    33             int sz = q.size();
    34             for(int k=0; k<sz; k++) {
    35                 vector<int> cur = q.front();
    36                 q.pop();
    37                 board[cur[0]][cur[1]] = '$';
    38                 for(vector<int> d:dir) {
    39                     int i = cur[0]+d[0], j = cur[1]+d[1];
    40                     if(isValid(i, j, m, n) && visited[i][j] != 1 && board[i][j] == 'O') {
    41                         q.push({i, j});
    42                         visited[i][j] = 1;
    43                     }
    44                 }
    45             }
    46         }
    47         for(int i=0; i<m; i++) {
    48             for(int j=0; j<n; j++) {
    49                 if(board[i][j] == '$') board[i][j] = 'O';
    50                 else if(board[i][j] == 'O') board[i][j] = 'X';
    51             }
    52         }
    53         return;
    54     }
    55 };

    解法二:Disjoint Set

    将所有无法转化 X 的 O 连接到一起,标记到 dummy=m*n 这个值(不存在于数组坐标0~m*n-1)

    首先,将四边缘上的 O 与 dummy 连接。

    然后遍历所有坐标,若存在 O,将其与其四个方向上的节点相连。

    这时有两种情况:

    • 这个 O 最终连接上了 dummy:那么该节点无法转化为 X
    • 这个 O 最终没有连接上 dummy:那么该节点需要转化为 X

    最后再遍历一次所有坐标,对于 O 的节点

    若没连接上 dummy,那么转化为 X

    代码参考:

     1 class Solution {
     2 public:
     3     bool isValid(int i, int j, int m, int n) {
     4         if(i<0 || j<0 || i>=m || j>=n) return false;
     5         return true;
     6     }
     7     void solve(vector<vector<char>>& board) {
     8         int m = board.size(), n = board[0].size();
     9         vector<vector<int>> dir = {{1,0},{-1,0},{0,1},{0,-1}};
    10         DisjointSet ds(m*n+1);
    11         for(int i=0; i<m; i++) {
    12             if(board[i][0] == 'O') ds.merge(i*n+0, m*n);
    13             if(board[i][n-1] == 'O') ds.merge(i*n+(n-1), m*n);
    14         }
    15         for(int j=0; j<n; j++) {
    16             if(board[0][j] == 'O') ds.merge(0+j, m*n);
    17             if(board[m-1][j] == 'O') ds.merge((m-1)*n+j, m*n);
    18         }
    19         for(int i=1; i<m-1; i++) {
    20             for(int j=1; j<n-1; j++) {
    21                 if(board[i][j] == 'O') {
    22                     for(vector<int> d:dir) {
    23                         int x = i+d[0], y = j+d[1];
    24                         if(board[x][y] == 'O') {
    25                             ds.merge(i*n+j, x*n+y);
    26                         }
    27                     }
    28                 }
    29                 
    30             }
    31         }
    32         for(int i=1; i<m-1; i++) {
    33             for(int j=1; j<n-1; j++) {
    34                 if(board[i][j] == 'O' && !ds.isConnected(i*n+j, m*n)) {
    35                     board[i][j] = 'X';
    36                 }
    37             }
    38         }
    39         return;
    40     }
    41 };

    Disjoint Set 类

     1 class DisjointSet {
     2 public:
     3     DisjointSet(int n):root(n,0),rank(n,0) {
     4         for(int i=0; i<n; i++) {
     5             root[i]=i;
     6         }
     7     }
     8     int find(int i) {
     9         if(root[i]!=i) {
    10             root[i] = find(root[i]);
    11         }
    12         return root[i];
    13     }
    14     void merge(int x, int y) {
    15         int x_root = find(x);
    16         int y_root = find(y);
    17         if(x_root == y_root) return ;
    18         if(rank[x_root]>rank[y_root]) {
    19             root[y_root] = x_root;
    20         } else if(rank[x_root]<rank[y_root]) {
    21             root[x_root] = y_root;
    22         } else {
    23             root[y_root] = x_root;
    24             rank[x_root] ++;
    25         }
    26         return ;
    27     }
    28     bool isConnected(int x, int y) {
    29         int x_root = find(x);
    30         int y_root = find(y);
    31         return x_root==y_root;
    32     }
    33 private:
    34     vector<int> root;
    35     vector<int> rank;
    36 };
  • 相关阅读:
    C#生成安装文件后自动附加数据库的思路跟算法
    c#压缩和解压缩文件
    如何远程备份sql server数据库
    计算一年中的第几周/c#得到阳历对应农历日期
    C·处理数据库备份
    字符串提取替换后再替换回去 和 函数将数字转换中文数字
    Visual C#的Excel编程
    数据库备份和恢复
    blog
    请问谁知道DOTMSN中打开聊天对话框的方法是什么?
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/14446385.html
Copyright © 2020-2023  润新知