【LeetCode】Surrounded Regions

本文探讨了如何解决二维棋盘中被X包围的O区域的问题,提出了两种解决方案:一种是使用深度优先搜索(DFS)递归实现;另一种是采用广度优先搜索(BFS)方法,后者更加高效稳定。

题目描述:

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
第一反应想到的方法是通过DFS递归来实现,代码如下(使用了一个新的vector来记录该点有没有走过,实际上有更简单的方法,将走过的值改为另一个字符,比如'V'来作为标记即可):

class Solution {
public:
	int N;
	void solve(vector<vector<char>> &board)
	{
		vector<vector<bool>> mark;
		N = board.size();
		for (int i = 0; i < N; i++)
		{
			vector<bool> line(board.size(), false);
			mark.push_back(line);
		}
		for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++)
		{
			if (board[i][j] == 'O'&&!mark[i][j])
				cover(mark, board, i, j);
		}
	}
	bool cover(vector<vector<bool>> &mark, vector<vector<char>> &board, int currX, int currY)
	{
		if (board[currX][currY] == 'X')
			return true;
		if (mark[currX][currY])
			return false;
		cout << currX << "  " << currY << "\r\n";
		//确定四个方向的点
		int x[4], y[4];
		x[0] = currX;
		y[0] = currY - 1;
		x[1] = currX;
		y[1] = currY + 1;
		x[2] = currX - 1;
		y[2] = currY;
		x[3] = currX + 1;
		y[3] = currY;
		mark[currX][currY] = true;
		if (currX == 0 || currX == N - 1 || currY == 0 || currY == N - 1)
			return false;
		for (int i = 0; i < 4; i++)
		{
			if (x[i] >= 0 && x[i] < N && y[i] >= 0 && y[i] < N && mark[x[i]][y[i]])
				continue;
			if (x[i] >= N || y[i] >= N || x[i] < 0 || y[i] < 0 || !cover(mark, board, x[i], y[i]))
				return false;
		}
		board[currX][currY] = 'X';
		return true;
	}
};

但是当遇到大规模矩阵时用DFS会出现stack overflow,因此考虑使用BFS来实现。

判定一个'O'是否被'X'只需看O是否能走到边界,因此通过BFS找出所有与边界线上的O相连的O即可,其余O全部翻为X。代码如下:

class Solution {
public:
	int row, col;
	queue<int> bfs;
	void solve(vector<vector<char>> &board)
	{
		if (board.empty())
			return;
		row = board.size();
		col = board[0].size();
		
		for (int i = 0; i < col; i++)
		{
			//上边
			if (board[0][i] == 'O')
				BFS(board, i);
			//下边
			if (board[row - 1][i] == 'O')
				BFS(board, (row - 1)*col + i);
		}
		for (int i = 0; i < row; i++)
		{
			//左边
			if (board[i][0] == 'O')
				BFS(board, i*col);
			//右边
			if (board[i][col - 1] == 'O')
				BFS(board, i*col + col - 1);
		}
		for (int i = 0; i < row; i++)
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == 'O')
				board[i][j] = 'X';
			if (board[i][j] == 'V')
				board[i][j] = 'O';
		}
	}
	void BFS(vector<vector<char>> &board, int index)
	{
		board[index / col][index % col] = 'V';
		bfs.push(index);
		while (!bfs.empty())
		{
			int ind = bfs.front();
			bfs.pop();
			int x = ind / col;
			int y = ind % col;
			//tips:会导致大量重复操作
			//board[x][y] = 'V';
			if (x - 1 >= 0 && board[x - 1][y] == 'O')
			{
				board[x - 1][y] = 'V';
				bfs.push((x - 1)*col + y);
			}
			if (x + 1 < row&&board[x + 1][y] == 'O')
			{
				board[x + 1][y] = 'V';
				bfs.push((x + 1)*col + y);
			}
			if (y - 1 >= 0 && board[x][y - 1] == 'O')
			{
				board[x][y - 1] = 'V';
				bfs.push(x*col + y - 1);
			}
			if (y + 1 < col&&board[x][y + 1] == 'O')
			{
				board[x][y + 1] = 'V';
				bfs.push(x*col + y + 1);
			}
		}
	}
};

需要注意的一点是:将O标记为V的操作应当在插入queue之前就进行,否则会影响下次循环的判定导致大量重复操作!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值