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'; } } }
相关文章推荐
- 操作系统开发系列—1.HelloWorld ●
- hdoj2015/hdoj2016/hdoj2017
- go on
- Android AES加密算法及其实现
- Android: 解决GridView、ListView在ScrollView中出现冲突的问题
- 判断变量和常量是否存在
- JAVA中使用Scanner连续输入int和String错误的解决方案
- JSTL
- 数据挖掘之特征选择
- EL表达式隐式对象
- IOS开发之UIScrollViewDelegate详解
- 关于Class.getResource和ClassLoader.getResource的路径问题
- API基础开发学习网址
- android笔记之ListView的setEmptyView方法
- iOS--UILabel字体默认宽度和高度
- JAVA中的Scanner类(IO)[JAVA][译]
- 关于mysql解压缩版安装的问题
- android 自定义折线图
- C++ 容器及选用总结
- git学习笔记