一天一道LeetCode

本系列文章已全部上传至我的github,地址:ZeeCoder‘s Github

欢迎大家关注我的新浪微博,我的新浪微博

欢迎转载,转载请注明出处

(一)题目

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

(二)解题

本题大意:棋盘上放满了‘X’和‘O’,将所有被‘X’包围的’O’全部转换成‘X’

需要注意被’X‘包围必须是上下左右都被包围。

这道题我最开始的做法是:遍历整个棋盘,当碰到一个’O‘之后,就采用广度搜索的方法,从上下左右四个方向上进行搜索,为’O‘就标记下来,如果搜索过程中碰到边界就代表此范围不能被’X‘包围,就不做处理;反之,如果没有碰到边界就把标记下来的’O‘全部转换成’X‘。

这种做法不好之处就是:需要找遍棋盘中所有的’O‘集合。

于是就采用逆向思维,从边界出发,已经判定这块’O’集合为不被’X‘包围的集合,这样就大大减少了搜索量。

  1. class Solution {
  2. public:
  3. void solve(vector<vector<char>>& board) {
  4. if(board.empty()) return;
  5. int row = board.size();
  6. int col = board[0].size();
  7. for(int i = 0 ; i < row ; i++)//从左、右边界开始往里面搜
  8. {
  9. if(board[i][0]=='O') isSurroundendBy(board,row,col,i,0);
  10. if(board[i][col-1]=='O') isSurroundendBy(board,row,col,i,col-1);
  11. }
  12. for(int i = 1 ; i < col-1 ; i++)//从上、下边界开始往里面搜
  13. {
  14. if(board[0][i]=='O') isSurroundendBy(board,row,col,0,i);
  15. if(board[row-1][i]=='O') isSurroundendBy(board,row,col,row-1,i);
  16. }
  17. for(int i = 0 ; i < row ; i++)//遍历棋盘,将标记的’1‘还原成’O‘,将’O‘改写成’X‘
  18. {
  19. for(int j = 0 ; j < col ;j++)
  20. {
  21. if(board[i][j] == 'O') board[i][j] = 'X';
  22. else if(board[i][j] == '1') board[i][j] = 'O';
  23. }
  24. }
  25. }
  26. void isSurroundendBy(vector<vector<char>>& board, int& row, int& col, int i, int j)
  27. {
  28. if(board[i][j] =='O'){
  29. board[i][j] = '1';//标记需要修改的’O‘
  30. //上下左右四个方向搜索
  31. if (i+1<row&&board[i+1][j]=='O') isSurroundendBy(board, row, col, i+1, j);
  32. if (i-1>=0&&board[i-1][j]=='O') isSurroundendBy(board, row, col, i-1, j);
  33. if (j+1<col&&board[i][j+1]=='O') isSurroundendBy(board, row, col, i, j+1);
  34. if (j-1>=0&&board[i][j-1]=='O') isSurroundendBy(board, row, col, i, j-1);
  35. }
  36. }
  37. };

于是兴高采烈的提交代码,结果Runtime Error!

递归的缺点显露出来了,递归深度太深,导致堆栈溢出。

接下来就把递归版本转换成迭代版本,消除递归带来的堆栈消耗。

  1. class Solution {
  2. public:
  3. void solve(vector<vector<char>>& board) {
  4. int row = board.size();
  5. if(row==0) return;
  6. int col = board[0].size();
  7. for(int i = 0 ; i < row ; i++)//从左、右边界开始往里面
  8. {
  9. if(board[i][0]=='O') isSurroundendBy(board,row,col,i,0);
  10. if(board[i][col-1]=='O') isSurroundendBy(board,row,col,i,col-1);//从上、下边界开始往里面
  11. }
  12. for(int i = 0 ; i < col ; i++)
  13. {
  14. if(board[0][i]=='O') isSurroundendBy(board,row,col,0,i);
  15. if(board[row-1][i]=='O') isSurroundendBy(board,row,col,row-1,i);
  16. }
  17. for (int i = 0; i < row; i++)//遍历棋盘修改标记
  18. {
  19. for (int j = 0; j < col; j++)
  20. {
  21. if (board[i][j] == 'O') board[i][j] = 'X';
  22. if (board[i][j] == '1') board[i][j] = 'O';
  23. }
  24. }
  25. }
  26. int X[4] = {-1,0,1,0};//四个方向
  27. int Y[4] = { 0,-1,0,1 };
  28. void isSurroundendBy(vector<vector<char>>& board, int& row, int& col, int i, int j)
  29. {
  30. stack<pair<int, int>> temp_stack;//用堆栈来存储中间变量
  31. temp_stack.push(make_pair(i, j));
  32. board[i][j] = '1';
  33. while (!temp_stack.empty())//堆栈不为空就代表没有处理完
  34. {
  35. int y = temp_stack.top().first;
  36. int x = temp_stack.top().second;
  37. temp_stack.pop();//出栈
  38. for (int idx = 0; idx < 4; idx++)//处理出栈坐标四个方向是否存在‘O’
  39. {
  40. int y0 = y + Y[idx];
  41. int x0 = x + X[idx];
  42. if (y0 >= 0 && y0 < row&&x0 >= 0 && x0 < col)
  43. {
  44. if (board[y0][x0] == 'O')//为'O'就压栈等待后续处理
  45. {
  46. board[y0][x0] = '1';
  47. temp_stack.push(make_pair(y0, x0));
  48. }
  49. }
  50. }
  51. }
  52. }
  53. };

提交代码,AC,16ms!

更多关于递归和迭代的转换可以参考本人的这篇博文:【数据结构与算法】深入浅出递归和迭代的通用转换思想

【一天一道LeetCode】#130. Surrounded Regions的更多相关文章

  1. [LeetCode] 130. Surrounded Regions 包围区域

    Given a 2D board containing 'X' and 'O'(the letter O), capture all regions surrounded by 'X'. A regi ...

  2. Leetcode 130. Surrounded Regions

    Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. A reg ...

  3. Java for LeetCode 130 Surrounded Regions

    Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...

  4. leetcode 130 Surrounded Regions(BFS)

    Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...

  5. Leetcode 130 Surrounded Regions DFS

    将内部的O点变成X input X X X XX O O X X X O XX O X X output X X X XX X X XX X X XX O X X DFS的基本框架是 void dfs ...

  6. leetcode 200. Number of Islands 、694 Number of Distinct Islands 、695. Max Area of Island 、130. Surrounded Regions

    两种方式处理已经访问过的节点:一种是用visited存储已经访问过的1:另一种是通过改变原始数值的值,比如将1改成-1,这样小于等于0的都会停止. Number of Islands 用了第一种方式, ...

  7. 130. Surrounded Regions(M)

    130.Add to List 130. Surrounded Regions Given a 2D board containing 'X' and 'O' (the letter O), capt ...

  8. 【LeetCode】130. Surrounded Regions (2 solutions)

    Surrounded Regions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A ...

  9. [LeetCode] 130. Surrounded Regions_Medium tag: DFS/BFS

    Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. A reg ...

随机推荐

  1. Linux平台安装MongoDB

    MongoDB 提供了 linux 各发行版本 64 位的安装包,你可以在官网下载安装包. 下载地址:https://www.mongodb.com/download-center#community ...

  2. day07 Cookie 和 Session(非常重要)

    day07 Cookie 和 Session 1. 会话技术 2. cookie 的方法和 cookie 案例-显示用户上次访问网站的时间 3. cookie 的细节 - 删除 cookie 4. S ...

  3. jupyter notebook 更换主题的方法

    参考 https://github.com/dunovank/jupyter-themes install with pip # install jupyterthemes pip install j ...

  4. python while条件和if判断的总练习

    输出123456 89的数字 num =1 while num < 11: if num == 7: pass else: print(num) num = num + 1 输出1-100的奇数 ...

  5. Dynamics CRM 不同的站点地图下设置默认不同的仪表板

    CRM的默认仪表板只能设置一个,也就是说每个引用仪表板的站点地图下点开仪表板后都是看到的默认仪表板,例如我下图中的"日常维修仪表板" 那如果我要在不同的站点地图下看到的默认仪表板不 ...

  6. Dynamics CRM2016 关闭错误报告弹框提示

    在之前的版本中错误报告的弹框提示是可以在隐私首选项中设置关闭的,如下图所示 但是在2016中这个设置没了 有人说在右上角的选项中设置,但那个只能是设置个人的无法修改系统级别的.在系统中找了半天还是没有 ...

  7. GDAL库进度信息编写示例

    GDAL进度信息编写 GDAL库中的算法以及读写数据的时候一般都会提供两个与进度信息相关的参数,下面分别进行描述: GDALProgressFunc pfnProgress void * pProgr ...

  8. Mac小技巧:强制退出程序的六种方法

    原帖地址: http://www.cnbeta.com/articles/175447.htm 1.使用键盘快捷键强制退出处于活跃状态的Mac程序 快捷键:Command+Option+Shift+E ...

  9. app控件唯一相对Xpath自动生成(增强版uiautomatorviewer)

    作者:cryanimal QQ:164166060 工具由来 前面的一篇博文较详细地介绍了uiautomatorviewer:扫描和分析Android应用程序的UI控件的工具. 熟悉控件获取的同学都知 ...

  10. Android必知必会-Android Studio修改包名

    如果移动端访问不佳,请尝试–> Github版 背景 公司做相似产品较多,一般都是以某个产品为基础修改,逐步替换设计图的切图.这个就会导致需要经常为Copy的项目修改包名. 这里是参考一些网上的 ...