您的位置:首页 > 其它

LeetCode 130. Surrounded Regions

2016-03-30 12:21 309 查看

1. 题目描述

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

2. 解题思路

拿到这道题目, 感觉和opencv 里面求图像连通域的思路有些像, 在 X 的大区域上 分布了几个 O 的区域, 那么我们只要提取出这几个区域, 判断出他们是否符合我们的需求, 符合需求的替换成 X 不就 O 了吗。

我们一开始想到的思路是使用 DFS, 可惜 超时了, 由于递归深度太大, 后来改用 BFS, AC了。

3. code

class Solution_DFS {
public:
void solve(vector<vector<char>>& board) {
if (board.size() == 0)
return;

int tag_id = 0;
// DFS 标记连通域
for (int i = 0; i != board.size(); i++){
for (int j = 0; j != board[0].size(); j++){
if (board[i][j] != target_o)
continue;

DFS(board, i, j, tag_id);
tag_id++;
}

}
// 检测连通域 是否符合要求, 不符合要求的集合
unordered_set<char> myset;
for (int i = 0; i != board.size(); i++){
if (board[i][0] != target_x)
myset.insert(board[i][0]);

if (board[i][board[0].size() - 1] != target_x)
myset.insert(board[i][board[0].size() - 1]);
}
for (int i = 0; i != board[0].size(); i++){
if (board[0][i] != target_x)
myset.insert(board[0][i]);

if (board[board.size() - 1][i] != target_x)
myset.insert(board[board.size() - 1][i]);
}

// 恢复所有不符合要求的连通域
for (int i = 0; i != board.size(); i++){
for (int j = 0; j != board[0].size(); j++){
char tmp = board[i][j];
if (tmp == target_x)
continue;

if (myset.find(tmp) != myset.end())
board[i][j] = target_o;
else
board[i][j] = target_x;
}
}
}
private:
void DFS(vector<vector<char>>& board, int row, int col, int tag_id){
if (row < board.size() && col < board[0].size() && board[row][col] == target_o){
board[row][col] = tag_id;

DFS(board, row + 1, col, tag_id);
DFS(board, row - 1, col, tag_id);
DFS(board, row, col + 1, tag_id);
DFS(board, row, col - 1, tag_id);
}
}

const char target_o = 'o';
const char target_x = 'x';
};

class Solution{
public:
void solve(vector<vector<char>>& board) {
if (board.size() == 0)
return;

int tag_id = 0;
// BFS 标记连通域
for (int i = 0; i != board.size(); i++){
for (int j = 0; j != board[0].size(); j++){
if (board[i][j] != target_o)
continue;

BFS(board, i, j, tag_id);
tag_id++;
}

}
// 检测连通域 是否符合要求, 不符合要求的集合
unordered_set<char> myset;
for (int i = 0; i != board.size(); i++){
if (board[i][0] != target_x)
myset.insert(board[i][0]);

if (board[i][board[0].size() - 1] != target_x)
myset.insert(board[i][board[0].size() - 1]);
}
for (int i = 0; i != board[0].size(); i++){
if (board[0][i] != target_x)
myset.insert(board[0][i]);

if (board[board.size() - 1][i] != target_x)
myset.insert(board[board.size() - 1][i]);
}

// 恢复所有不符合要求的连通域
for (int i = 0; i != board.size(); i++){
for (int j = 0; j != board[0].size(); j++){
char tmp = board[i][j];
if (tmp == target_x)
continue;

if (myset.find(tmp) != myset.end())
board[i][j] = target_o;
else
board[i][j] = target_x;
}
}
}
private:
void BFS(vector<vector<char>>& board, int row, int col, int tag_id){
if (isOK(board, row, col)){
queue<array<int, 2>> myqueue;
myqueue.push(array<int, 2>{{ row, col }});
while (!myqueue.empty()){
array<int, 2> front = myqueue.front();
myqueue.pop();
board[row][col] = tag_id;

vector<array<int, 2>> around{ array<int, 2>{{ front[0] + 1, front[1] }},
array<int, 2>{{ front[0] - 1, front[1] }},
array<int, 2>{{ front[0], front[1] + 1}},
array<int, 2>{{ front[0], front[1] - 1}} };

for (int i = 0; i != around.size(); i++){
if (isOK(board, around[i][0], around[i][1])){
board[around[i][0]][around[i][1]] = tag_id;
myqueue.push(around[i]);
}
}
}
}
}

inline bool isOK(vector<vector<char>>& board, int row, int col){
if (row < board.size() && col < board[0].size() && board[row][col] == target_o)
return true;
return false;
}

const char target_o = 'O';
const char target_x = 'X';
};


4. 大神代码

下面两段 代码, DFS 和 BFS 都有一个相似之处, 都是从边缘开始出发进行搜索, 这样就不需要处理中间较大的孤岛区域了。

4.1 DFS

X X X X           X X X X             X X X X
X X O X  ->       X X O X    ->       X X X X
X O X X           X 1 X X             X O X X
X O X X           X 1 X X             X O X X

class Solution {
public:
void solve(vector<vector<char>>& board) {
int i,j;
int row=board.size();
if(!row)
return;
int col=board[0].size();

for(i=0;i<row;i++){
check(board,i,0,row,col);
if(col>1)
check(board,i,col-1,row,col);
}
for(j=1;j+1<col;j++){
check(board,0,j,row,col);
if(row>1)
check(board,row-1,j,row,col);
}
for(i=0;i<row;i++)
for(j=0;j<col;j++)
if(board[i][j]=='O')
board[i][j]='X';
for(i=0;i<row;i++)
for(j=0;j<col;j++)
if(board[i][j]=='1')
board[i][j]='O';
}
void check(vector<vector<char> >&vec,int i,int j,int row,int col){
if(vec[i][j]=='O'){
vec[i][j]='1';
if(i>1)
check(vec,i-1,j,row,col);
if(j>1)
check(vec,i,j-1,row,col);
if(i+1<row)
check(vec,i+1,j,row,col);
if(j+1<col)
check(vec,i,j+1,row,col);
}
}
};


4.2 BFS

void bfsBoundary(vector<vector<char> >& board, int w, int l)
{
int width = board.size();
int length = board[0].size();
deque<pair<int, int> > q;
q.push_back(make_pair(w, l));
board[w][l] = 'B';
while (!q.empty()) {
pair<int, int> cur = q.front();
q.pop_front();
pair<int, int> adjs[4] = {{cur.first-1, cur.second},
{cur.first+1, cur.second},
{cur.first, cur.second-1},
{cur.first, cur.second+1}};
for (int i = 0; i < 4; ++i)
{
int adjW = adjs[i].first;
int adjL = adjs[i].second;
if ((adjW >= 0) && (adjW < width) && (adjL >= 0)
&& (adjL < length)
&& (board[adjW][adjL] == 'O')) {
q.push_back(make_pair(adjW, adjL));
board[adjW][adjL] = 'B';
}
}
}
}

void solve(vector<vector<char> > &board) {
int width = board.size();
if (width == 0) //Add this to prevent run-time error!
return;
int length = board[0].size();
if  (length == 0) // Add this to prevent run-time error!
return;

for (int i = 0; i < length; ++i)
{
if (board[0][i] == 'O')
bfsBoundary(board, 0, i);

if (board[width-1][i] == 'O')
bfsBoundary(board, width-1, i);
}

for (int i = 0; i < width; ++i)
{
if (board[i][0] == 'O')
bfsBoundary(board, i, 0);
if (board[i][length-1] == 'O')
bfsBoundary(board, i, length-1);
}

for (int i = 0; i < width; ++i)
{
for (int j = 0; j < length; ++j)
{
if (board[i][j] == 'O')
board[i][j] = 'X';
else if (board[i][j] == 'B')
board[i][j] = 'O';
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: