方法一:union find
class UF {
public:
UF(int n):cnt(n), weights(n, 1) {
for (int i = 0; i < n; ++i)
roots.push_back(i);
}
int findRoot(int p) {
while (roots[p] != p)
p = roots[p];
return p;
}
void Union(int p, int q) {
int pRoot = findRoot(p), qRoot = findRoot(q);
if (pRoot == qRoot)
return;
else {
if (weights[pRoot] < weights[qRoot]) {
roots[pRoot] = qRoot;
weights[qRoot] += weights[pRoot];
} else {
roots[qRoot] = pRoot;
weights[pRoot] += weights[qRoot];
}
--cnt;
}
}
bool isConnected(int p, int q) {
return findRoot(p) == findRoot(q);
}
int weight(int p) {
return weights[findRoot(p)];
}
int count() {
return cnt;
}
private:
vector<int> roots;
vector<int> weights;
int cnt;
};
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[0].empty())
return;
int rows = board.size(), cols = board[0].size();
UF uf(rows*cols);
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j) {
if (board[i][j] == 'X')
continue;
if (i > 0 && board[i-1][j] == 'O')
uf.Union(index(i, j, cols), index(i-1, j, cols));
if (j > 0 && board[i][j-1] == 'O')
uf.Union(index(i, j, cols), index(i, j-1, cols));
}
set<int> boardRoot;
for (int i = 0; i < rows; ++i) {
if (board[i][0] == 'O')
boardRoot.insert(uf.findRoot(index(i, 0, cols)));
if (board[i][cols-1] == 'O')
boardRoot.insert(uf.findRoot(index(i, cols-1, cols)));
}
for (int j = 1; j < cols-1; ++j) {
if (board[0][j] == 'O')
boardRoot.insert(uf.findRoot(index(0, j, cols)));
if (board[rows-1][j] == 'O')
boardRoot.insert(uf.findRoot(index(rows-1, j, cols)));
}
for (int i = 1; i < rows-1; ++i)
for (int j = 1; j < cols-1; ++j) {
if (board[i][j] == 'X')
continue;
if (boardRoot.find(uf.findRoot(index(i, j, cols))) == boardRoot.end())
board[i][j] = 'X';
}
}
private:
int index(int row, int col, int cols) {
return row * cols + col;
}
};
方法二:bfs
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[0].empty())
return;
int rows = board.size(), cols = board[0].size();
vector<vector<bool>> visited(rows, vector<bool>(cols, false));
queue<pair<int, int>> q;
for (int i = 0; i < rows; ++i) {
if (board[i][0] == 'O') {
visited[i][0] = true;
q.push(make_pair(i, 0));
}
if (board[i][cols-1] == 'O') {
visited[i][cols-1] = true;
q.push(make_pair(i, cols-1));
}
}
for (int j = 1; j < cols-1; ++j) {
if (board[0][j] == 'O') {
visited[0][j] = true;
q.push(make_pair(0, j));
}
if (board[rows-1][j] == 'O') {
visited[rows-1][j] = true;
q.push(make_pair(rows-1, j));
}
}
vector<vector<int>> dirs{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
while (!q.empty()) {
auto p = q.front();
q.pop();
int x = p.first, y = p.second;
for (int i = 0; i < 4; ++i) {
int newX = x + dirs[i][0];
int newY = y + dirs[i][1];
if (newX >= 0 && newX < rows && newY >= 0 && newY < cols && board[newX][newY] == 'O' && !visited[newX][newY]) {
visited[newX][newY] = true;
q.push(make_pair(newX, newY));
}
}
}
for (int i = 1; i < rows-1; ++i)
for (int j = 1; j < cols-1; ++j)
if (board[i][j] == 'O' && !visited[i][j])
board[i][j] = 'X';
}
};
//bfs确实是从目的地开始扩散比较好
方法三:dfs
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[0].empty())
return;
int rows = board.size(), cols = board[0].size();
vector<vector<bool>> visited(rows, vector<bool>(cols, false));
for (int i = 0; i < rows; ++i) {
helper(board, visited, i, 0);
helper(board, visited, i, cols-1);
}
for (int j = 1; j < cols-1; ++j) {
helper(board, visited, 0, j);
helper(board, visited, rows-1, j);
}
for (int i = 1; i < rows-1; ++i)
for (int j = 1; j < cols-1; ++j) {
if (board[i][j] == 'O' && !visited[i][j])
board[i][j] = 'X';
}
}
private:
void helper(vector<vector<char>>& board, vector<vector<bool>>& visited, int i, int j) {
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || board[i][j] == 'X' || visited[i][j])
return;
visited[i][j] = true;
helper(board, visited, i-1, j);
helper(board, visited, i+1, j);
helper(board, visited, i, j-1);
helper(board, visited, i, j+1);
}
};
另外说一句,一开始没有想到从边上的格子进行dfs,想的是规矩地从上到下从左到右的dfs,还想到了乱七八糟的dfs方案。后来想到从边上开始才简单了。