Given a 2D board containing ‘X’ and ‘O’, capture all regions surrounded by ‘X’.
A region is captured by flipping all ‘O’s into ‘X’s in that surrounded region.
For example,
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X
这道题体现了基本的搜索算法,体现了经典的深度优先算法和广度优先算法。
深度优先算法:
我刚开始的思路是单独设立一个矩阵来标记是否走过,以及是区分出不同的O的集合区,以便遍历之后可以确定是否为转换区。结果超时!
现附上一种Runtime error的DFS算法:
void search(vector<vector<char>>& board,vector<vector<char>>& visit,int r,int c,bool& success,int count){
if(r<0||r>=board.size()||c<0||c>=board[0].size()){
success=true;
return;//success 'O' is valid
}
if(board[r][c]=='X'||visit[r][c]!='0') return;//go on searching
visit[r][c]=count+'0';
search(board,visit,r+1,c,success,count);
search(board,visit,r-1,c,success,count);
search(board,visit,r,c+1,success,count);
search(board,visit,r,c-1,success,count);
}
void solve(vector<vector<char>>& board) {
if(board.size()==0) return;
map<int,int> cc;
int count=0;//record Nth search
vector<vector<char>> visit(board.size(),vector<char>(board[0].size(),'0'));
for(int i=0;i<board.size();i++){
for(int j=0;j<board[0].size();j++){
if(board[i][j]=='X'||visit[i][j]!='0') continue;
++count;
bool success=false;
search(board,visit,i,j,success,count);
if(!success) cc[count]=count;
}
}
for(int r=0;r<board.size();r++){
for(int c=0;c<board[0].size();c++){
if(board[r][c]=='X'||cc.find(visit[r][c])==cc.end()) continue;
board[r][c]='X';
}
}
}
其实这种思路麻烦了,首先没有必要设立一个标记矩阵visit。换个思路想一下,什么情况是不用转换的呢,那么就是至少有一个O是在边上的。这里我们先从边上开始搜索,找出边界为O的格子,然后顺着这个格子进行DFS搜索。将和该格子联通的O全变为另一个字符(例如V);
最后再将O(需要转换的区域)变为X,将V变为O;
这种思路如果仍然采用递归,就是比上面的少设定了一个矩阵,节省了O(N)的空间。时间上其实没什么改变。
代码仍然超时!
void dfs(int row, int col,vector<vector<char> >& board)
{
if(row < 0 || row >= board.size() || col < 0 || col >= board[0].size()) return;
if(board[row][col] != 'O') return;
board[row][col] = 'V';
dfs(row - 1, col, board);//up
dfs(row, col + 1, board);//right
dfs(row + 1, col, board);//down
dfs(row, col - 1, board);//left
}
void solve(vector<vector<char> > &board)
{
if(board.size() == 0 || board[0].size() == 0)
return;
int rows = board.size();
int cols = board[0].size();
for(int i = 0; i < rows; ++i){
dfs(i, 0, board);
dfs(i, cols - 1, board);
}
for (int j = 0; j < cols; ++j)
{
dfs(0, j, board);
dfs(rows - 1, j, board);
}
for(int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
{
if(board[i][j] == 'O')
board[i][j] = 'X';
else if(board[i][j] == 'V')
board[i][j] = 'O';
}
}
既然递归超时,那么采用非递归形式的DFS。(20ms)
struct cordinate{
int row,col;
void set(int r,int c){
row=r;
col=c;
}
cordinate(int r,int c):row(r),col(c){}
};
void solve(vector<vector<char>>& board) {
if(board.size()==0||board[0].size()==0) return;
int row=board.size();
int col=board[0].size();
queue<cordinate> q;
cordinate point(0,0);
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O'&&(i==0||i==row-1||j==0||j==col-1)) DFS(board,i,j);
}
}
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O') board[i][j]='X';
else if(board[i][j]=='V') board[i][j]='O';
}
}
}
void DFS(vector<vector<char>>& board,int i,int j){
int row=board.size();
int col=board[0].size();
stack<cordinate> q;
cordinate point(i,j);
board[i][j]='V';
q.push(point);
while(!q.empty()){
point=q.top();
int r=point.row;
int c=point.col;
if(r<row-1&&board[r+1][c]=='O'){//right
board[r+1][c]='V';
point.set(r+1,c);
q.push(point);
continue;
}
if(c>0&&board[r][c-1]=='O'){//down
board[r][c-1]='V';
point.set(r,c-1);
q.push(point);
continue;
}
if(r>0&&board[r-1][c]=='O'){//left
board[r-1][c]='V';
point.set(r-1,c);
q.push(point);
continue;
}
if(c<col-1&&board[r][c+1]=='O'){//up
board[r][c+1]='V';
point.set(r,c+1);
q.push(point);
continue;
}
q.pop();
}
}
道理差不多,再写一个BFS的。(16ms)比DFS速度略快。
struct cordinate{
int row,col;
void set(int r,int c){
row=r;
col=c;
}
cordinate(int r,int c):row(r),col(c){}
};
void solve(vector<vector<char>>& board) {
if(board.size()==0||board[0].size()==0) return;
int row=board.size();
int col=board[0].size();
queue<cordinate> q;
cordinate point(0,0);
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O'&&(i==0||i==row-1||j==0||j==col-1)) DFS(board,i,j);
}
}
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O') board[i][j]='X';
else if(board[i][j]=='V') board[i][j]='O';
}
}
}
void DFS(vector<vector<char>>& board,int i,int j){
int row=board.size();
int col=board[0].size();
stack<cordinate> q;
cordinate point(i,j);
board[i][j]='V';
q.push(point);
while(!q.empty()){
point=q.top();
int r=point.row;
int c=point.col;
if(r<row-1&&board[r+1][c]=='O'){//right
board[r+1][c]='V';
point.set(r+1,c);
q.push(point);
continue;
}
if(c>0&&board[r][c-1]=='O'){//down
board[r][c-1]='V';
point.set(r,c-1);
q.push(point);
continue;
}
if(r>0&&board[r-1][c]=='O'){//left
board[r-1][c]='V';
point.set(r-1,c);
q.push(point);
continue;
}
if(c<col-1&&board[r][c+1]=='O'){//up
board[r][c+1]='V';
point.set(r,c+1);
q.push(point);
continue;
}
q.pop();
}
}