Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
前言
力扣第130题 被围绕的区域 如下所示:
给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。
示例 1:
输入: board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出: [["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解释: 被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
一、思路
题目比较有意思,就是找到矩阵中被围住的 O 并用 X 填上。这一题可能一开始很难想到怎么做,但是题目中示例解答已经给出了具体的提示:被围绕的区间不会存在于边界上
既然我们直到了边界上的 O 不会被围住,那么就可以将边界中的 O 作为切人点。我刚开始的想法如下所示:
- 按层序遍历
- 第一层碰到
O就是没有被围住的,做一个标记 - 第二层时碰到
O看看能不能通过外层的O出去 - ......,直到遍历到内部的最后一层
后来发现这样会导致无法发现那些间接连通的 O,如下图所示(红色标注的):
既然不能通过 层序遍历 的方式,那要怎么做呢?
下面的思路我也是看官方题解的 tnt
我们可以从最外层的 O 出发,找到与其(直接或间接)关联的 O。这种方式有一点需要注意一下:寻找的过程中不能回头,不然会导致栈溢出
以图中右下角的 O 作为例子,它的路径是这样的:
经过上面的分析,这一题大致步骤为:使用 深度遍历,将最外层的元素作为起点,找到所有与其关联的 O。然后再遍历一遍矩阵,将所有没有关联的 O 填上 X 即可。
二、实现
实现代码
实现代码与思路中保持一致,我使用了另一个二维矩阵 flag 用于记录关联的 O
int n, m;
int[][] flag;
public void solve(char[][] board) {
n = board.length;
if (n == 0) {
return;
}
m = board[0].length;
flag = new int[n][m];
for (int i = 0; i < n; i++) {
dfs(board, i, 0);
dfs(board, i, m - 1);
}
for (int i = 1; i < m - 1; i++) {
dfs(board, 0, i);
dfs(board, n - 1, i);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (board[i][j] == 'O' && flag[i][j] == 0) {
board[i][j] = 'X';
}
}
}
}
public void dfs(char[][] board, int x, int y) {
if (x < 0 || x >= n || y < 0 || y >= m || board[x][y] != 'O' || flag[x][y] == -1) {
return;
}
flag[x][y] = -1;
dfs(board, x + 1, y);
dfs(board, x - 1, y);
dfs(board, x, y + 1);
dfs(board, x, y - 1);
}
测试代码
public static void main(String[] args) {
char[][] board = {{'O','X','X','O','X'},{'X','O','O','X','O'},{'X','O','X','O','X'},{'O','X','O','O','O'},{'X','X','O','X','O'}};
char[][] board1 = {{'X','O','X','O','X','O'},{'O','X','O','X','O','X'},{'X','O','X','O','X','O'},{'O','X','O','X','O','X'}};
new Number130().solve(board1);
System.out.println("test");
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~