题目描述
给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。
找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
示例:
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’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
思路
此题可以使用并查集,首先进行遍历,将所有相邻的’O’归于一个集合里面,同时,将边界上的’O’与一个虚拟的节点归为一个集合以作区分。然后,再次遍历,将所有既是’O’又不和那个虚拟节点一个集合的元素改成’X’输出。
代码
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
| class Union{ vector<int> pre; public: Union(n){ pre.resize(n); for(int i=0; i<n; i++) pre[i] = i; } int search(int root){ int son, temp; son = root; while(root != pre[root]) root = pre[root]; while(son != root){ temp = pre[son]; pre[son] = root; son = temp; } return root; } void join(int x, int y){ int root1 = search(x); int root2 = search(y); if(root1 != root2) pre[root2] = root1; } boolean isConnect(int node1, int node2){ return search(node1) == search(node2); } }; class Solution { public: void solve(vector<vector<char>>& board) { if(board.size() == 0) return; int row,col; row = board.size(); col = board[0].size(); dsu set = dsu(row*col+1); for(int i=0; i<row; i++) for(int j=0; j<col; j++){ if(board[i][j] == 'O'){ if(i==0||j==0||i==row-1||j==col-1){ set.join(row*col, node(i,j,col)); }else{ if(board[i-1][j] == 'O') set.join(node(i-1,j,col), node(i,j,col)); if(board[i+1][j] == 'O') set.join(node(i+1,j,col), node(i,j,col)); if(board[i][j-1] == 'O') set.join(node(i,j-1,col), node(i,j,col)); if(board[i][j+1] == 'O') set.join(node(i,j+1,col), node(i,j,col)); } } } for(int i=0; i<row; i++){ for(int j=0; j<col; j++){ if(board[i][j] == 'O'&&set.isConnect(node(i,j,col),row*col)!=1) board[i][j] = 'X'; } } } int node(int i, int j, int col){ return j+i*col; } };
|
注意
不要忘记考虑数组为空的情况
在这道题,使用并查集并不是很优的解法,后面可以使用其他方法。