被围绕的区域
给你一个 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"]]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 200
board[i][j]
为'X'
或'O'
代码:
//DFS
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty()) return;
int rows = board.size(), cols = board[0].size();
// 从边界开始查找,转换
for (int i = 0; i < rows; ++i) {
if (board[i][0] == 'O') dfs(board, i, 0);
if (board[i][cols - 1] == 'O') dfs(board, i, cols - 1);
}
for (int i = 0; i < cols; ++i) {
if (board[0][i] == 'O') dfs(board, 0, i);
if (board[rows - 1][i] == 'O') dfs(board, rows - 1, i);
}
// 恢复转换 和 设置X元素
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (board[i][j] == 'O') board[i][j] = 'X';
if (board[i][j] == '#') board[i][j] = 'O';
}
}
}
private:
void dfs(vector<vector<char>>& board, int row, int col) {
if (row < 0 || row == board.size() || col < 0 ||
col == board[0].size() || board[row][col] != 'O') return;
board[row][col] = '#';
dfs(board, row + 1, col), dfs(board, row, col + 1);
dfs(board, row - 1, col), dfs(board, row, col - 1);
}
};
//BFS
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty()) return;
int rows = board.size(), cols = board[0].size();
// 从边界开始查找,转换
for (int i = 0; i < rows; ++i) {
if (board[i][0] == 'O') bfs(board, i, 0);
if (board[i][cols - 1] == 'O') bfs(board, i, cols - 1);
}
for (int i = 0; i < cols; ++i) {
if (board[0][i] == 'O') bfs(board, 0, i);
if (board[rows - 1][i] == 'O') bfs(board, rows - 1, i);
}
// 恢复转换 和 设置 X元素
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (board[i][j] == 'O') board[i][j] = 'X';
if (board[i][j] == '#') board[i][j] = 'O';
}
}
}
private:
void bfs(vector<vector<char>>& board, int i, int j) {
int m = board.size(), n = board[0].size();
deque<pair<int, int>> worker{ {i,j} };
while (worker.size()) {
auto sub = worker.front();
auto &row = sub.first, &col = sub.second;
worker.pop_front();
if (row < 0 || row == m || col < 0 || col == n
|| board[row][col] != 'O') continue;
board[row][col] = '#';
worker.push_back({row + 1, col});
worker.push_back({row - 1, col});
worker.push_back({row, col + 1});
worker.push_back({row, col - 1});
}
}
};
//并查集
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty()) return;
int m = board.size(), n = board[0].size();
ufSet(m * n + 1);
for (int row = 0; row < m; ++row) {
for (int col = 0; col < n; ++col) {
if (board[row][col] == 'X') continue;
if (!col || !row || row + 1 == m || col + 1 == n)
merge(m * n, row * n + col); // m * n 值,为集合头
if (col > 0 && board[row][col - 1] == 'O')
merge(row * n + col - 1, row * n + col);
if (row > 0 && board[row - 1][col] == 'O')
merge((row - 1) * n + col, row * n + col);
}
}
for (int row = 0; row < m; ++row) {
for (int col = 0; col < n; ++col) {
// 通过 find 返回集合头来确实是否是第三种元素集
if (board[row][col] == 'O' && find(row * n + col) != m * n)
board[row][col] = 'X';
}
}
}
private:
void ufSet(int n) {
uf.resize(n);
for (int i = 0; i < n; ++i)
uf[i] = i;
}
int find(int p) {
return uf[p] == p ? p : uf[p] = find(uf[p]);
}
void merge(int p, int q) {
// 保持 uf.size()-1 为集合头
int p1 = find(p), q2 = find(q);
p1 == uf.size() - 1 ? uf[q2] = p1 : uf[p1] = q2;
}
private:
vector<int> uf;
};