Leetcode Surrounded Regions

本文转自:http://hombo.wang/leetcode/2014/10/06/surrounded-regions/


这是一道图搜索题,关键在于用DFS或BFS搜索时,处理好边界条件和其他限制条件,例如遇到‘X’就停止这条路的搜索。

原文题目:

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,


 
 
  1. X X X X
  2. X O O X
  3. X X O X
  4. X O X X

After running your function, the board should be:


 
 
  1. X X X X
  2. X X X X
  3. X X X X
  4. X O X X

分析:

题目的意思是说把这个2D board中完全被'X'包住的'O'的区域全部替换为'X',就像上面给出的一个例子,内部的三个'O'被替换了,而边界的'O'由于没有被包住而不需要替换。

这道题其实就是一个图的搜索问题,可以把这个2D board看成由几个连通子图构成的,连通子图由全O或者全X构成

搜索的过程是这样的:


 
 
  1. 1. 从头开始遍历这个2D board 如果遇到一个`O` ,就从这个`O` 开始进行DFS或者BFS遍历它的连通子图,边界条件就是遇到`X`或者board的边界停止。我们知道连通子图之间是没有路径的,这样就不会对其他子图产生影响。
  2.  
  3. 2. 在遍历的过程中,不断判断是否有`O`board的边界,如果有,就标记这个子图为`需要替换为‘X’的子图`,在遍历结束后将这个子图中的元素全部替换成`X`。子图的存储可以用一个vector实现。
  4.  
  5. 3. 然后继续在board中往后找没有被访问过的`O`,继续上面的过程,直至结束。

这样我们就完成了题目的要求。

这里用DFSBFS都行,时间复杂度是O(n),由于要借助一定空间来做标记和存储子图,所以空间复杂度是O(n)

这个只给出用DFSAC的代码,BFS的实现方式把stack换成queue就行了。


 
 
  1. class Solution {
  2. public:
  3. void solve(vector<vector<char>> &board) {
  4. if(board.size()<=2||board[0].size()<=2) return;
  5. stack<pair<int,int>> s; //DFS stack
  6. int xsize = board.size(), ysize = board[0].size();
  7. vector<vector<bool>> record(xsize,vector<bool>(ysize,false)); // 访问标记
  8. vector<pair<int,int>> canlist; //存储连通子图
  9. bool can = true;
  10. for(int i = 1 ; i < xsize-1 ; ++i){
  11. for(int j = 1 ; j < ysize-1 ; ++j){ //遍历所有未访问的‘O’
  12. if(board[i][j] == 'O'&&!record[i][j]){
  13. can = true;
  14. s.push(make_pair(i,j));
  15. canlist.push_back(make_pair(i,j));
  16. record[i][j] = true;
  17. while(!s.empty()){ //DFS
  18. pair<int,int> p = s.top();
  19. s.pop();
  20. if(can&&(p.first==0||p.first==xsize-1||p.second==0||p.second==ysize-1))
  21. can = false;
  22. if((p.first>0)&&board[p.first-1][p.second]=='O'&&!record[p.first-1][p.second]){
  23. s.push(make_pair(p.first-1,p.second));
  24. record[p.first-1][p.second] = true;
  25. canlist.push_back(make_pair(p.first-1,p.second));
  26. }
  27. if((p.first<xsize-1)&&board[p.first+1][p.second]=='O'&&!record[p.first+1][p.second]){
  28. s.push(make_pair(p.first+1,p.second));
  29. record[p.first+1][p.second] = true;
  30. canlist.push_back(make_pair(p.first+1,p.second));
  31. }
  32. if((p.second>0)&&board[p.first][p.second-1]=='O'&&!record[p.first][p.second-1]){
  33. s.push(make_pair(p.first,p.second-1));
  34. record[p.first][p.second-1] = true;
  35. canlist.push_back(make_pair(p.first,p.second-1));
  36. }
  37. if((p.second<ysize-1)&&board[p.first][p.second+1]=='O'&&!record[p.first][p.second+1]){
  38. s.push(make_pair(p.first,p.second+1));
  39. record[p.first][p.second+1] = true;
  40. canlist.push_back(make_pair(p.first,p.second+1));
  41. }
  42. }
  43. if(can){ //改变连通子图中的'O'为‘X’
  44. for(int w = 0 ; w < canlist.size() ; ++w)
  45. board[canlist[w].first][canlist[w].second] = 'X';
  46. }
  47. canlist.clear();
  48. }
  49. }
  50. }
  51. }
  52. };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值