题目
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
思路一:深度优先+Flag
深度优先 DFS 遍历矩阵的边缘元素,将O相连的区域赋值为1,其他的为0,在将flag标志为0的board置为X。
实现代码
class Solution {
public:
void solve(vector<vector<char>> &board) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int rows = board.size();
if(rows<=0)
return;
int cols = board[0].size();
vector<vector<int>> flag(rows,vector<int>(cols,0));
for(int i=0;i<rows;i++)
{
dfs(i,0,board,flag);
dfs(i,cols-1,board,flag);
}
for(int j=0;j<cols;j++)
{
dfs(0,j,board,flag);
dfs(rows-1,j,board,flag);
}
for(int i=1;i<rows-1;i++)
for(int j=0;j<cols;j++)
{
if(flag[i][j]==0)
board[i][j]='X';
}
return;
}
void dfs(int i,int j,vector<vector<char>> &board,vector<vector<int>> &flag)
{
int rows = board.size();
int cols = board[0].size();
if(i<0||i>=rows||j<0||j>=cols)
return ;
if(board[i][j]=='X')
return ;
if(board[i][j]=='O' && flag[i][j]==0)
{
flag[i][j]=1;
dfs(i,j-1,board,flag);
dfs(i,j+1,board,flag);
dfs(i+1,j,board,flag);
dfs(i-1,j,board,flag);
}
}
};
注意:要对 flag 数组初始化 vector<vector<int>> flag(rows,vector<int>(cols,0)); 否则会出现错误。
上述运行结果是 对于 Juge Small 运行正确,但是对于 Juge Large 会出现 Runtime Error 。
因该是 运行时内存溢出,主要是用到了 flag 数组。其实完全不必用到的。下面的改进。
思路二:深度优先
1、First scan the four edges of the board, if you meet an 'O', call a recursive mark function to mark that region to something else (for example, '+');
2、scan all the board, if you meet an 'O', flip it to 'X';
3、scan again the board, if you meet an '+', flip it to 'O';
step 2 and 3 can be merged.
然后我实现的代码如下:
class Solution {
public:
void dfs(int i,int j,vector<vector<char>> &board)
{
if(i<0 || i>=board.size() || j<0 || j>=board[0].size() )
return;
if(board[i][j]=='O')
{
board[i][j]='#';
dfs(i,j+1,board);
dfs(i,j-1,board);
dfs(i-1,j,board);
dfs(i+1,j,board);
}
}
void solve(vector<vector<char>> &board) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int rows = board.size();
if(rows<=2)
return ;
int cols = board[0].size();
for(int i=0;i<rows;i++)
{
dfs(i,0,board);
dfs(i,cols-1,board);
}
for(int j=1;j<cols-1;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';
if(board[i][j]=='#')
board[i][j]='O';
}
return;
}
};
这样就可以完全的 Juge Large 了。
思路三:广度优先BFS
class Solution {
private:
struct Node
{
int x,y;
Node(){};
Node(int a,int b):x(a),y(b){};
};
public:
void solve(vector<vector<char>> &board) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int rows = board.size();
if(rows<=2) return ;
int cols = board[0].size();
queue<Node> myqueue;
for(int i=0;i<rows;i++)
{
if(board[i][0]=='O')
{
board[i][0]='#';
myqueue.push(Node(i,0));
}
if(board[i][rows-1]=='O')
{
board[i][rows-1]='#';
myqueue.push(Node(i,rows-1));
}
}
for(int j=1;j<cols-1;j++)
{
if(board[0][j]=='O')
{
board[0][j]='#';
myqueue.push(Node(0,j));
}
if(board[cols-1][j]=='O')
{
board[cols-1][j]='#';
myqueue.push(Node(cols-1,j));
}
}
const int Direct[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
while(!myqueue.empty())
{
Node mynode = myqueue.front();
myqueue.pop();
for(int i=0;i<4;i++)
{
int tx = mynode.x+Direct[i][0];
int ty = mynode.y+Direct[i][1];
if(tx<0 || tx>=board.size() || ty<0 || ty>=board[0].size() || board[tx][ty]!='O')
continue ;
board[tx][ty]='#';
myqueue.push(Node(tx,ty));
}
}
for(int i=0;i<rows;i++)
for(int j=0;j<cols;j++)
{
if(board[i][j]=='O')
board[i][j]='X';
if(board[i][j]=='#')
board[i][j]='O';
}
}
};
当然可以不用建立 Node 结构体,而是 queue<pair<int, int>> Q; Q.push(make_pair(i , j)); 来实现。
速度更快。
最新版本:
public class Solution {
// use a queue to do BFS
private Queue<Integer> queue = new LinkedList<Integer>();
public void solve(char[][] board) {
if(board == null){
return;
}
int row = board.length;
if(row <= 2) {
return;
}
int col = board[0].length;
if(col <= 2){
return;
}
for(int i=0; i<row; i++){
if(board[i][0] == 'O'){
bfs(i, 0, board);
}
if(board[i][col-1] == 'O'){
bfs(i, col-1, board);
}
}
for(int j=0; j<col-1; j++){
if(board[0][j] == 'O'){
bfs(0, j, board);
}
if(board[row-1][j] == 'O'){
bfs(row-1, j, board);
}
}
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] == '#'){
board[i][j] = 'O';
}
}
}
}
private void bfs(int i, int j, char[][] board) {
int row = board.length;
int col = board[0].length;
fillCell(i, j, board);
while(!queue.isEmpty()){
int cur = queue.poll();
int m = cur/col;
int n = cur%col;
fillCell(m+1, n, board);
fillCell(m-1, n, board);
fillCell(m, n+1, board);
fillCell(m, n-1, board);
}
}
private void fillCell(int i, int j, char[][] board){
int row = board.length;
int col = board[0].length;
if(i < 0 || i >= row || j < 0 || j>=col){
return;
}
if(board[i][j] == 'O'){
board[i][j] = '#';
queue.offer(i*col+j);
}
}
// DFS: Line 50: java.lang.StackOverflowError
private void dfs(int i, int j, char[][] board) {
int row = board.length;
int col = board[0].length;
if(i < 0 || i >= row || j < 0 || j>=col){
return;
}
if(board[i][j] == 'O'){
board[i][j] = '#';
dfs(i+1, j, board);
dfs(i-1, j, board);
dfs(i, j+1, board);
dfs(i, j-1, board);
}
}
}