Surrounded Region 跟 Num of Islands 同类思路。唯一不同的是,对四条边的边界点的判定标准不同。前者认为,边界点不是被包围的点,后者认为是。
我一直都不习惯递归的算法,所以很多遍历题都用了stack或者queue来一步一步遍历。
这题的思路是:你可以选择检测被包围的区域,也可以选择不被包围的区域。显然,由于不被包围的区域都是与四周边界点相关的,所以后者的速度更快些。
【我的思路是】:遍历整个board,检测被包围的区域,BFS+queue (40+ms)
class Solution {
public:
void solve(vector<vector<char>>& board) {
if(board.empty()||board[0].empty())
return ;
vector<vector<char>> & b=board; //拷贝一个board 的副本。在board上修改,用b来判断包围区域。
vector<vector<bool>> visit(board.size(),vector<bool>(board[0].size(),false));
queue<pair<int,int>> qu;
vector<vector<int>> dir(4,vector<int>(2));
dir[0][0]=-1;dir[0][1]=0;dir[1][0]=1;dir[1][1]=0;dir[2][0]=0;dir[2][1]=-1;dir[3][0]=0;dir[3][1]=1;
int i,j,k;
int row=b.size(),col=b[0].size();
for(i=0;i<row;i++){
for(j=0;j<col;j++){
if(b[i][j]=='X'||visit[i][j])
continue;
qu.push(make_pair(i,j));
visit[i][j]=true;
bool sur=true;
vector<pair<int,int>> pos;
while(!qu.empty()){
pair<int,int>p=qu.front();
if(p.first==0||p.first==row-1||p.second==0||p.second==col-1)
sur=false; //<span style="font-family: Arial, Helvetica, sans-serif;">发现这块都是‘O’的区域有边界点,所以不是合法的surrounded region。即便如此,我们也要把这整块区域找出来,以便防止它干扰其他区域的判断。</span>
pos.push_back(p);
qu.pop();
for(k=0;k<dir.size();k++){
int first=dir[k][0]+p.first;
int second=dir[k][1]+p.second;
if(first>=0&&first<row&&second>=0&&second<col&&b[first][second]=='O'&&!visit[first][second]){
visit[first][second]=true;
qu.push(make_pair(first,second));
}
}
}
if(sur){ //找到了surrounded region,capture 它。
for(k=0;k<pos.size();k++){
board[pos[k].first][pos[k].second]='X';
}
}
pos.clear();
}
}
}
};
遍历四周的边界点,把不合法的包围区域暂时mark为其他字符,比如‘M’。BFS+queue
再遍历整个board,如果检测到‘M’,复原成‘O’;如果检测到‘O’,说明是没被mark过的,即合法的包围区域,复制为‘X’
void mark(vector<vector<char>> & board,int ii,int jj){
queue<pair<int,int>> qu;
board[ii][jj]='M';
qu.push(make_pair(ii,jj));
int i,j,k;
int row=board.size(),col=board[0].size();
vector<vector<int>> dir(4,vector<int>(2));
dir[0][0]=0;dir[0][1]=1;
dir[1][0]=0;dir[1][1]=-1;
dir[2][0]=1;dir[2][1]=0;
dir[3][0]=-1;dir[3][1]=0;
while(!qu.empty()){
pair<int,int> p=qu.front();
qu.pop();
for(k=0;k<dir.size();k++){
int first=dir[k][0]+p.first;
int second=dir[k][1]+p.second;
if(first>=0&&first<row&&second>=0&&second<col&&board[first][second]=='O'){
board[first][second]='M';
qu.push(make_pair(first,second));
}
}
}
}
void solve(vector<vector<char>>& board){
if(board.empty()||board[0].empty())
return ;
int row=board.size();
int col=board[0].size();
int i,j,k;
<span style="white-space:pre"> </span>// 遍历四条边,检测不合法的包围区域并mark
for(i=0;i<col;i++){
if(board[0][i]=='O')
mark(board,0,i);
if(board[row-1][i]=='O')
mark(board,row-1,i);
}
for(i=0;i<row;i++){
if(board[i][0]=='O')
mark(board,i,0);
if(board[i][col-1]=='O')
mark(board,i,col-1);
}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>// 遍历整个board,复原不合法的包围区域+capture合法包围区域
for(i=0;i<row;i++){
for(j=0;j<col;j++){
if(board[i][j]=='O')
board[i][j]='X';
else if(board[i][j]=='M')
board[i][j]='O';
}
}
}