给你一个 m x n
的矩阵 board
,由若干字符 'X'
和 'O'
,找到所有被 'X'
围绕的区域,并将这些区域里所有的 '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"]]
解释: 被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
示例 2:
输入: board = [["X"]]
输出: [["X"]]
思路 本次用并查集不用dfs了
- 创建一个虚拟节点,把4条边上所有O和该节点关联,
- 遍历矩阵联通,连接右下节点【因为我们从左到右从上到下遍历,左上方的节点认为已经合并过了】
- 遍历所有O,看是否和虚拟节点同一个连通图,不是的话就变成X
class Solution {
int[][] direction = {{1, 0}, {0, 1}};
int rows;
int cols;
//联通类问题,本次用uf解,
// 1)创建一个虚拟节点,把4条边上所有O和该节点关联,
//2)遍历矩阵联通,连接右下节点【因为我们从左到右从上到下遍历,左上方的节点认为已经合并过了】
//3)遍历所有O,看是否和虚拟节点同一个连通图,不是的话就变成X
public void solve(char[][] board) {
rows = board.length;
cols = board[0].length;
UnionFind unionFind = new UnionFind(cols * rows + 1);
//虚拟节点连接所有O边缘节点
int dummyNode = rows * cols;
// 填写第 1 行和最后一行
for (int j = 0; j < cols; j++) {
if (board[0][j] == 'O') {
unionFind.union(getIndex(0, j), dummyNode);
}
if (board[rows - 1][j] == 'O') {
unionFind.union(getIndex(rows - 1, j), dummyNode);
}
}
// 填写第 1 列和最后一列
for (int i = 1; i < rows - 1; i++) {
if (board[i][0] == 'O') {
unionFind.union(getIndex(i, 0), dummyNode);
}
if (board[i][cols - 1] == 'O') {
unionFind.union(getIndex(i, cols - 1), dummyNode);
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 'O') {
for (int[] d : direction) {
int newX = i + d[0];
int newY = j + d[1];
if (newX < rows && newY < cols && board[newX][newY] == 'O')
unionFind.union(getIndex(newX, newY), getIndex(i, j));
}
}
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 'O' && !unionFind.isConnect(getIndex(i, j), dummyNode))
board[i][j] = 'X';
}
}
}
public int getIndex(int x, int y) {
return x * cols + y;
}
public class UnionFind {
//每个位置的父节点
int[] parents;
public UnionFind(int n) {
parents = new int[n];
for (int i = 0; i < n; i++) {
parents[i] = i;
}
}
public int find(int i) {
while (parents[i] != i) {
i = parents[i];
}
return i;
}
public boolean isConnect(int x, int y) {
return find(x) == find(y);
}
public void union(int x, int y) {
int px = find(x);
int py = find(y);
if (px == py)
return;
parents[px] = py;
return;
}
}
}
dfs解法
class Solution {
int[][] direction = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
public void solve(char[][] board) {
//想到沿着边dfs所有的O,标记为T,然后遍历把所有的o变为X
int row = board.length;
int col = board[0].length;
boolean[][] visited = new boolean[row][col];
for(int i = 0; i < row; i++){
if(board[i][0] == 'O' && visited[i][0] == false){
dfs(board, visited, i, 0);
}
if(board[i][col-1] == 'O' && visited[i][col-1] == false){
dfs(board, visited, i, col-1);
}
}
for(int j = 0; j < col; j++){
if(board[0][j] == 'O' && visited[0][j] == false){
dfs(board, visited, 0, j);
}
if(board[row-1][j] == 'O' && visited[row-1][j] == false){
dfs(board, visited, row-1 , j);
}
}
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(board[i][j] == 'O')
board[i][j] = 'X';
}
}
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(board[i][j] == 'T')
board[i][j] = 'O';
}
}
return;
}
public void dfs(char[][] board, boolean[][] visited, int row, int col){
if(!inArea(board, row, col) || board[row][col] != 'O' || visited[row][col]){
return;
}
board[row][col] = 'T';
visited[row][col] = true;
for(int i = 0; i < 4; i++){
dfs(board, visited, direction[i][0]+row, direction[i][1]+col);
}
return;
}
public boolean inArea(char[][] board, int x, int y) {
if (y < 0 || y >= board[0].length || x < 0 || x >= board.length)
return false;
return true;
}
}
```