一天一道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‘包围的集合,这样就大大减少了搜索量。

class Solution {
public:
    void solve(vector<vector<char>>& board) {
        if(board.empty()) return;
        int row = board.size();
        int col = board[0].size();
        for(int i = 0 ; i < row ; i++)//从左、右边界开始往里面搜
        {
            if(board[i][0]=='O') isSurroundendBy(board,row,col,i,0);
            if(board[i][col-1]=='O') isSurroundendBy(board,row,col,i,col-1);
        }
        for(int i = 1 ; i < col-1 ; i++)//从上、下边界开始往里面搜
        {
            if(board[0][i]=='O') isSurroundendBy(board,row,col,0,i);
            if(board[row-1][i]=='O') isSurroundendBy(board,row,col,row-1,i);
        }
        for(int i = 0 ; i < row ; i++)//遍历棋盘,将标记的’1‘还原成’O‘,将’O‘改写成’X‘
        {
            for(int j = 0 ; j < col ;j++)
            {
                if(board[i][j] == 'O') board[i][j] = 'X';
                else if(board[i][j] == '1') board[i][j] = 'O';
           }
        }
    }
    void isSurroundendBy(vector<vector<char>>& board, int& row, int& col, int i, int j)
    {
        if(board[i][j] =='O'){
            board[i][j] = '1';//标记需要修改的’O‘
                //上下左右四个方向搜索
            if (i+1<row&&board[i+1][j]=='O') isSurroundendBy(board, row, col, i+1, j);
            if (i-1>=0&&board[i-1][j]=='O') isSurroundendBy(board, row, col, i-1, j);
            if (j+1<col&&board[i][j+1]=='O') isSurroundendBy(board, row, col, i, j+1);
            if (j-1>=0&&board[i][j-1]=='O') isSurroundendBy(board, row, col, i, j-1);
        }
    }
};

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

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

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

class Solution {
public:
    void solve(vector<vector<char>>& board) {
        int row = board.size();
        if(row==0) return;
        int col = board[0].size();
        for(int i = 0 ; i < row ; i++)//从左、右边界开始往里面
        {
            if(board[i][0]=='O') isSurroundendBy(board,row,col,i,0);
            if(board[i][col-1]=='O') isSurroundendBy(board,row,col,i,col-1);//从上、下边界开始往里面
        }
        for(int i = 0 ; i < col ; i++)
        {
            if(board[0][i]=='O') isSurroundendBy(board,row,col,0,i);
            if(board[row-1][i]=='O') isSurroundendBy(board,row,col,row-1,i);
        }
        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] == '1') board[i][j] = 'O';
            }
        }
    }
    int X[4] = {-1,0,1,0};//四个方向
    int Y[4] = { 0,-1,0,1 };
    void isSurroundendBy(vector<vector<char>>& board, int& row, int& col, int i, int j)
    {
        stack<pair<int, int>> temp_stack;//用堆栈来存储中间变量
        temp_stack.push(make_pair(i, j));
        board[i][j] = '1';
        while (!temp_stack.empty())//堆栈不为空就代表没有处理完
        {
            int y = temp_stack.top().first;
            int x = temp_stack.top().second;
            temp_stack.pop();//出栈
            for (int idx = 0; idx < 4; idx++)//处理出栈坐标四个方向是否存在‘O’
            {
                int y0 = y + Y[idx];
                int x0 = x + X[idx];
                if (y0 >= 0 && y0 < row&&x0 >= 0 && x0 < col)
                {
                    if (board[y0][x0] == 'O')//为'O'就压栈等待后续处理
                    {
                        board[y0][x0] = '1';
                        temp_stack.push(make_pair(y0, x0));
                    }
                }
            }
        }
    }
};

提交代码,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. flask+apscheduler+redis实现定时任务持久化

    在我们开发flask的时候,我们会结合apscheduler实现定时任务,我们部署到服务器上,会不会遇到这样的问题,每次我们部署后,我们重启服务后,原来的定时任务都需要重启,这样对我们经常迭代的项目肯 ...

  2. EF实体的部分更新

    实现实体的部分更新假设实体InfoHotel如下: public class InfoHotel { public int Id{get;set;} public string Name{get;se ...

  3. Flume 读取RabbitMq消息队列消息,并将消息写入kafka

    首先是关于flume的基础介绍 组件名称 功能介绍 Agent代理 使用JVM 运行Flume.每台机器运行一个agent,但是可以在一个agent中包含多个sources和sinks. Client ...

  4. 深入浅出低功耗蓝牙(BLE)协议栈

    深入浅出低功耗蓝牙(BLE)协议栈 BLE协议栈为什么要分层?怎么理解蓝牙"连接"?如果蓝牙协议只有ATT没有GATT会发生什么? 协议栈框架 一般而言,我们把某个协议的实现代码称 ...

  5. 转:Xming + PuTTY 在Windows下远程Linux主机使用图形界面的程序

    一.原理Linux/Unix的X Window具有网络透明性.X Window系统里有一个统一的Server来负责各个程序与显示器.键盘和鼠标等输入输出设备的交互,每个有GUI的应用程序都通过网络协议 ...

  6. JavaScript中的事件模型

    JS中的事件 1.鼠标事件 onclick   ondbclick   onmouseover   onmouseout 2.HTML事件 onload   onunload   onsubmit   ...

  7. Android进阶 | 摆脱斗图 | 行业交流 | 深度学习 | 付费

    Android进阶 | 摆脱斗图 | 行业交流 | 深度学习 | 付费 其实在很早的时候我就有想过,是不是退出一些群,因为群太多了,里面的水友也多,基友也多,就难免会水起来,这样既耽误学习又耽误工作, ...

  8. Unity UGUI图文混排(七) -- 下划线

    之前更新超链接的时候,忘了搭配实现一个下划线的功能,这篇文章就是来补上这一个功能,时间有点长,一方面没有很好的思路,一方面也没多少时间. 先在网上收集了一下下划线的实现操作,一种是在文本下再创建一个文 ...

  9. [ExtJS5学习笔记]第三十三节 sencha extjs 5 grid表格导出excel

    使用extjs肯定少不了使用表格控件,用到表格,领导们(一般)还是惯于使用excel看数据,所以用到extjs表格的技术猿们肯定也会有导出表格excel这一个需求,本文主要针对如何在用extjs将gr ...

  10. antlr 4新特性总结及与antlr v3的不同

    antlr 4新特性总结及与antlr v3的不同 学习曲线低.antlr v4相对于v3,v4更注重于用更接近于自然语言的方式去解析语言.比如运算符优先级,排在最前面的规则优先级最高: 层次更清晰. ...