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

A region is captured by flipping all 'O's into 'X's in that surrounded region.

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

Explanation:

Surrounded regions shouldn’t be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. Two cells are connected if they are adjacent cells connected horizontally or vertically.

这是道关于 XXOO 的题,有点像围棋,将包住的O都变成X,但不同的是边缘的O不算被包围,跟之前那道 Number of Islands 很类似,都可以用 DFS 来解。刚开始我的思路是 DFS 遍历中间的O,如果没有到达边缘,都变成X,如果到达了边缘,将之前变成X的再变回来。但是这样做非常的不方便,在网上看到大家普遍的做法是扫矩阵的四条边,如果有O,则用 DFS 遍历,将所有连着的O都变成另一个字符,比如 \$,这样剩下的O都是被包围的,然后将这些O变成X,把$变回O就行了。代码如下:

解法一:

class Solution {
public:
void solve(vector<vector<char> >& board) {
for (int i = ; i < board.size(); ++i) {
for (int j = ; j < board[i].size(); ++j) {
if ((i == || i == board.size() - || j == || j == board[i].size() - ) && board[i][j] == 'O')
solveDFS(board, i, j);
}
}
for (int i = ; i < board.size(); ++i) {
for (int j = ; j < board[i].size(); ++j) {
if (board[i][j] == 'O') board[i][j] = 'X';
if (board[i][j] == '$') board[i][j] = 'O';
}
}
}
void solveDFS(vector<vector<char> > &board, int i, int j) {
if (board[i][j] == 'O') {
board[i][j] = '$';
if (i > && board[i - ][j] == 'O')
solveDFS(board, i - , j);
if (j < board[i].size() - && board[i][j + ] == 'O')
solveDFS(board, i, j + );
if (i < board.size() - && board[i + ][j] == 'O')
solveDFS(board, i + , j);
if (j > && board[i][j - ] == 'O')
solveDFS(board, i, j - );
}
}
};

很久以前,上面的代码中最后一个 if 中必须是 j > 1 而不是 j > 0,为啥 j > 0 无法通过 OJ 的最后一个大数据集合,博主开始也不知道其中奥秘,直到被另一个网友提醒在本地机子上可以通过最后一个大数据集合,于是博主也写了一个程序来验证,请参见验证 LeetCode Surrounded Regions 包围区域的DFS方法,发现 j > 0 是正确的,可以得到相同的结果。神奇的是,现在用 j > 0  也可以通过 OJ 了。

下面这种解法还是 DFS 解法,只是递归函数的写法稍有不同,但是本质上并没有太大的区别,参见代码如下:

解法二:

class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[].empty()) return;
int m = board.size(), n = board[].size();
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (i == || i == m - || j == || j == n - ) {
if (board[i][j] == 'O') dfs(board, i , j);
}
}
}
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (board[i][j] == 'O') board[i][j] = 'X';
if (board[i][j] == '$') board[i][j] = 'O';
}
}
}
void dfs(vector<vector<char>> &board, int x, int y) {
int m = board.size(), n = board[].size();
vector<vector<int>> dir{{,-},{-,},{,},{,}};
board[x][y] = '$';
for (int i = ; i < dir.size(); ++i) {
int dx = x + dir[i][], dy = y + dir[i][];
if (dx >= && dx < m && dy > && dy < n && board[dx][dy] == 'O') {
dfs(board, dx, dy);
}
}
}
};

我们也可以使用迭代的解法,但是整体的思路还是一样的,在找到边界上的O后,然后利用队列 queue 进行 BFS 查找和其相连的所有O,然后都标记上美元号。最后的处理还是先把所有的O变成X,然后再把美元号变回O即可,参见代码如下:

解法三:

class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[].empty()) return;
int m = board.size(), n = board[].size();
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (i != && i != m - && j != && j != n - ) continue;
if (board[i][j] != 'O') continue;
board[i][j] = '$';
queue<int> q{{i * n + j}};
while (!q.empty()) {
int t = q.front(), x = t / n, y = t % n; q.pop();
if (x >= && board[x - ][y] == 'O') {board[x - ][y] = '$'; q.push(t - n);}
if (x < m - && board[x + ][y] == 'O') {board[x + ][y] = '$'; q.push(t + n);}
if (y >= && board[x][y - ] == 'O') {board[x][y - ] = '$'; q.push(t - );}
if (y < n - && board[x][y + ] == 'O') {board[x][y + ] = '$'; q.push(t + );}
}
}
}
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (board[i][j] == 'O') board[i][j] = 'X';
if (board[i][j] == '$') board[i][j] = 'O';
}
}
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/130

类似题目:

Number of Islands

Walls and Gates

参考资料:

https://leetcode.com/problems/surrounded-regions/

https://leetcode.com/problems/surrounded-regions/discuss/41895/Share-my-clean-Java-Code

https://leetcode.com/problems/surrounded-regions/discuss/41825/Simple-BFS-solution-easy-to-understand

https://leetcode.com/problems/surrounded-regions/discuss/41612/A-really-simple-and-readable-C%2B%2B-solutionuff0conly-cost-12ms

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 130. Surrounded Regions 包围区域的更多相关文章

  1. [LeetCode] Surrounded Regions 包围区域

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

  2. 验证LeetCode Surrounded Regions 包围区域的DFS方法

    在LeetCode中的Surrounded Regions 包围区域这道题中,我们发现用DFS方法中的最后一个条件必须是j > 1,如下面的红色字体所示,如果写成j > 0的话无法通过OJ ...

  3. [LintCode] Surrounded Regions 包围区域

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

  4. Java for LeetCode 130 Surrounded Regions

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

  5. Surrounded Regions 包围区域——dfs

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

  6. Leetcode 130. Surrounded Regions

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

  7. 130. Surrounded Regions(周围区域问题 广度优先)(代码未完成!!)

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

  8. leetcode 130 Surrounded Regions(BFS)

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

  9. 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 ...

随机推荐

  1. javascript判断mp3是否播放完

    javascript判断mp3是否播放完 var audio=document.getElementById('audio'); if(audio){ audio.loop = false; audi ...

  2. HBuilder webApp开发(七)微信/QQ/新浪/腾讯微博分享

    链接 https://blog.csdn.net/zhuming3834/article/details/51706256

  3. linux安装redis步骤

    1.安装gcc  redis是c语言编写的 -- 安装命令 yum install gcc-c++ -- 检查gcc 是否安装 gcc -v 2.下载redis安装包,在root目录下执行 wget ...

  4. 宣布Visual Studio Code Installer for Java

    自从第一个Java语言服务器在微软苏黎世办公室的一个小型会议室的黑客马拉松中开发已经差不多3年了,该会议室的人员来自Red Hat,IBM,Codenvy和Microsoft,后来成为Visual S ...

  5. Jenkins配置LDAP认证

    managerdn即为连接到AD的账号

  6. Java面试题:Java中的集合及其继承关系

    关于集合的体系是每个人都应该烂熟于心的,尤其是对我们经常使用的List,Map的原理更该如此.这里我们看这张图即可: 1.List.Set.Map是否继承自Collection接口? List.Set ...

  7. webpack4 css modules

    demo 代码点此,webpack4 中通过 css-loader 开启 css 模块化, 开始前先做点准备工作. 不了解 css 模块化的,可以前往查看github_css_modules. ##准 ...

  8. 团队展示&选题 (白衣天使队)

    作业详见此地址:    https://www.cnblogs.com/bbplus/p/11735449.html

  9. Innodb整体架构

    如下图展示了Innodb内存中和磁盘的结构: 内存中结构主要有如下几种: buffer pool change buffer adaptive hash index (自适应的hash索引) Log ...

  10. PL/SQL Developer报错 ORA-12154:tns:could not resolve the connect identifier specified

    PL/SQL Developer使用预先配置数据库报错 ORA-12154:tns:could not resolve the connect identifier specified. 情况描述:我 ...