该题也是典型的DFS模板例题,但是我这里第一次做这道题犯了个错误——我(天真)知道所有边缘出现的“O”都是不可能变成“X”的,所以我直接在遍历数组的时候忽视边缘,然后就遇到“O”就用DFS将它周围的所有“O”都变成“X”
反应快的同学应该很快就看出来我上面的想法很明显是严重的审题错误!!!!!!!!!!!
因为我忽略了————在边缘与“O”相连的所有“O”也是不可能变成“X”的!!!!!!!!!!!
下面就是我第一次写的错误思路的代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param board char字符型vector<vector<>>
* @return char字符型vector<vector<>>
*/
int row,col,tx,ty,nextt[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
vector<vector<char> > surroundedArea(vector<vector<char> >& board) {
row=board.size();
col=board[0].size();
if(row==0||col==0)
return board;
for(int i=1;i<row;i++)
{
for(int j=1;j<col;j++)
{
if(i==row-1||j==col-1)
continue;
dfs(board,i,j);
}
}
return board;
}
void dfs(vector<vector<char> >& board,int x,int y)
{
if(board[x][y]=='O')
{
board[x][y]='X';
for(int k=0;k<=3;k++)
{
tx=x+nextt[k][0];
ty=y+nextt[k][1];
dfs(board,tx,ty);
}
}
return ;
}
};
实际上被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的
正确的思路应该是这样的我们先对所有边缘进行DFS搜索,如果遇到“O”就将这个“O”周围的“O”做个记号,最后遍历整个数组,如果遇到“O”就可以全部将其变成“X”了,最后再将做过记号的“O”全部变回来即可~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如下:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param board char字符型vector<vector<>>
* @return char字符型vector<vector<>>
*/
int row,col,tx,ty,nextt[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
vector<vector<char> > surroundedArea(vector<vector<char> >& board) {
row=board.size();
col=board[0].size();
for(int i=0;i<row;i++)//分别搜索四条边缘的O,并把它们及与其相连的O全都变成A
dfs(board,i,0);
for(int i=0;i<row;i++)
dfs(board,i,col-1);
for(int i=0;i<col;i++)
dfs(board,0,i);
for(int i=0;i<col;i++)
dfs(board,row-1,i);
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
if(board[i][j]=='O')//把没变成A的O变成X
board[i][j]='X';
else if(board[i][j]=='A')//把A还原为O
board[i][j]='O';
}
}
return board;
}
void dfs(vector<vector<char> >& board,int x,int y)
{
if(board[x][y]=='O')
{
board[x][y]='A';
for(int i=0;i<4;i++)
{
tx=x+nextt[i][0];
ty=y+nextt[i][1];
if(tx<0||ty<0||tx>=row||ty>=col)
continue;
dfs(board,tx,ty);
}
}
return ;
}
};
下面是BFS的做法(思路与上述一致)
class Solution {
public:
int n, m, nextt[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
void bfs(vector<vector<char>>& board, int i, int j)
{
queue<pair<int, int>>q;
pair<int, int>now, next;
q.push({ i,j });
while (!q.empty())
{
now = q.front();
int x = now.first;
int y = now.second;
board[x][y] = 'A';
q.pop();
for (int i = 0; i < 4; i++)
{
int tx = x + nextt[i][0];
int ty = y + nextt[i][1];
if (tx < 0 || ty < 0 || tx >= n || ty >= m || board[tx][ty]!='O')
{
continue;//注意这里在遇到A的时候要continue,要不然会死循环
}
next.first = tx;
next.second = ty;
board[tx][ty] = 'A';
q.push(next);
}
}
}
void solve(vector<vector<char>>& board) {
n = board.size();
m = board[0].size();
for (int i = 0; i < m; i++)
{
if (board[0][i] == 'O')
{
bfs(board, 0, i);
}
if (board[n - 1][i] == 'O')
{
bfs(board, n - 1, i);
}
}
for (int i = 0; i < n; i++)
{
if (board[i][0] == 'O')
{
bfs(board, i, 0);
}
if (board[i][m - 1] == 'O')
{
bfs(board, i, m - 1);
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (board[i][j] == 'O')
{
board[i][j] = 'X';
}
if (board[i][j] == 'A')
{
board[i][j] = 'O';
}
}
}
}
};
下面是 并查集 的做法(思路与上述一致)
class Solution {
public:
class UF//将并查集做成类
{
public:
UF(int n):father(n)//初始化
{
for(int i=0;i<n;i++)
{
father[i]=i;
}
}
int find(int x)//查
{
if(x!=father[x])
{
return father[x]=find(father[x]);
}
return x;
}
void join(int a,int b)//并
{
father[find(a)]=find(b);
}
bool Issame(int a,int b)//判断二者“队长”是否一致
{
return find(a)==find(b);
}
private:
vector<int> father;
};
int nextt[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
void solve(vector<vector<char>>& board) {
int n=board.size();
int m=board[0].size();
UF uf(n*m+10);//初始化更大一点为下面的join做准备
for(int i=0;i<m;i++)//将边缘的O与m*n并起来(即上句话的作用)
{
if(board[0][i]=='O')
{
uf.join(i,m*n);
}
if(board[n-1][i]=='O')
{
uf.join((n-1)*m+i,m*n);
}
}
for(int j=0;j<n;j++)//将边缘的O与m*n并起来
{
if(board[j][0]=='O')
{
uf.join(j*m,m*n);
}
if(board[j][m-1]=='O')
{
uf.join(j*m+m-1,m*n);
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(board[i][j]=='O')//如果O的周围有O,就把它们并起来
{
for(int z=0;z<4;z++)
{
int tx=i+nextt[z][0];
int ty=j+nextt[z][1];
if(tx<0||ty<0||tx>=n||ty>=m||board[tx][ty]=='X')
{
continue;
}
uf.join(tx*m+ty,i*m+j);
}
}
}
}
for(int i=1;i<n-1;i++)
{
for(int j=1;j<m-1;j++)
{
if(board[i][j]=='O'&&!uf.Issame(i*m+j,m*n))//寻找没有与m*n并起来的O
{
board[i][j]='X';
}
}
}
}
};