被围绕的区域
给一个二维的矩阵,包含 'X'
和 'O'
, 找到所有被 'X' 围绕的区域,并用 '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
X O X X
class UnionFind{
private:
unordered_map<int, int> father;
public:
UnionFind(int n, int m){
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int id = i * m + j;
father[id] = id;
}
}
}
int find(int id){
int parent = id;
while(parent != father[parent]){
parent = father[parent];
}
return parent;
}
int compress_find(int id){
int parent = id;
while(parent != father[parent]){
parent = father[parent];
}
int fa = id;
while(fa != father[fa]){
int tmp = father[fa];
father[fa] = parent;
fa = tmp;
}
return parent;
}
void union_both(int a, int b){
int fa_a = compress_find(a);
int fa_b = compress_find(b);
if(fa_a != fa_b){
father[fa_a] = father[fa_b];
}
}
};
class Solution {
public:
/**
* @param board a 2D board containing 'X' and 'O'
* @return void
*/
// V1
//思路:目标是要找到由X包围起来的O的区域。
// 首先,外围一圈上的O肯定会保留下来。然后,从外围的O能达到的O也要保留。剩下其他的O就是内部的O。
// 所以方法就是从外围的一圈进行DFS算法:依次对外圈的“O”做DFS,将其可以到达O临时设置为#。
void surroundedRegions1(vector<vector<char>>& board) {
// Write your code here
if(board.size() == 0 || board[0].size() == 0)
return;
fillBoarder(board, 'O', '#');
replace(board, 'O', 'X');
fillBoarder(board, '#', 'O');
}
// BFS
void fillBoarder(vector<vector<char>>& board, char patten, char c){
int n = board.size();
int m = board[0].size();
queue<pair<int,int> > q;//save thoese with patten
// set those boarder pattern with c
for(int i = 0; i < board.size(); i++){
if(board[i][0] == patten){
board[i][0] = c;
q.push(make_pair(i, 0));
}
if(board[i][m-1] == patten){
board[i][m-1] = c;
q.push(make_pair(i, m-1));
}
}
for(int j = 1; j < m-1; j++){
if(board[0][j] == patten){
board[0][j] = c;
q.push(make_pair(0, j));
}
if(board[n-1][j] == patten){
board[n-1][j] = c;
q.push(make_pair(n-1, j));
}
}
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
while(!q.empty()){
int x = q.front().first;
int y = q.front().second;
q.pop();
for(int k = 0; k < 4; k++){
int nx = x + dx[k];
int ny = y + dy[k];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && board[nx][ny] == patten){
board[nx][ny] = c;
q.push(make_pair(nx, ny));
}
}
}
}
void replace(vector<vector<char>>& board, char patten, char c){
for(int i = 0; i < board.size(); i++){
for(int j = 0; j < board[0].size(); j++){
if(board[i][j] == patten){
board[i][j] = c;
}
}
}
}
// V2 类似于V1, but use DFS
void surroundedRegions(vector<vector<char>>& board) {
// Write your code here
if(board.size() == 0 || board[0].size() == 0)
return;
fillBoarderDFS(board, 'O', '#');
replace(board, 'O', 'X');
fillBoarderDFS(board, '#', 'O');
}
// DFS
void fillBoarderDFS(vector<vector<char>>& board, char patten, char c){
int n = board.size();
int m = board[0].size();
// set those boarder pattern with c
for(int i = 0; i < board.size(); i++){
fillDFS(board, i, 0, patten, c);
fillDFS(board, i, m-1, patten, c);
}
for(int j = 1; j < m-1; j++){
fillDFS(board, 0, j, patten, c);
fillDFS(board, n-1, j, patten, c);
}
}
void fillDFS(vector<vector<char>>& board, int x, int y, char patten, char c){
if(board[x][y] != patten){
return;
}
board[x][y] = c;
int n = board.size();
int m = board[0].size();
// set those boarder pattern with c
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
for(int k = 0; k < 4; k++){
int nx = x + dx[k];
int ny = y + dy[k];
if(nx >= 0 && nx < n && ny >= 0 && ny < m){
fillDFS(board, nx, ny, patten, c);
}
}
}
///
// V3 : Uinon Find
void surroundedRegions3(vector<vector<char>>& board) {
if(board.size() == 0 || board[0].size() == 0)
return;
int n = board.size();
int m = board[0].size();
UnionFind uf(n, m);
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
for(int k = 0; k < 4; k++){
int nx = i + dx[k];
int ny = j + dy[k];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && board[nx][ny] == board[i][j]){
int id = i * m + j;
int nid = nx * m + ny;
uf.union_both(id, nid);
}
}
}
}
// 将边角以及与其相邻的‘O’ 的father 加入set
unordered_set<int> set;
for(int i = 0; i < n; i++){
if(board[i][0] == 'O'){
int fa = uf.compress_find(i*m);
set.insert(fa);
}
if(board[i][m-1] == 'O'){
int fa = uf.compress_find(i * m + m - 1);
set.insert(fa);
}
}
for(int j = 1; j < m-1; j++){
if(board[0][j] == 'O'){
int fa = uf.compress_find(j);
set.insert(fa);
}
if(board[n-1][j] == 'O'){
int fa = uf.compress_find((n-1)*m + j);
set.insert(fa);
}
}
// 判断是否和边角的‘O’同一个group
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int fa = uf.find(i * m + j);
if(board[i][j] == 'O' && set.find(fa) == set.end()){
board[i][j] = 'X';
}
}
}
}
};