被围绕的区域(DFS/BFS/并查集)

 该题也是典型的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';
                }
            }
        }
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZZWWWFFF_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值