一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
一、题目 leetcode 被围绕的区域
给你一个 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'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
示例 2:
输入:board = [["X"]]
输出:[["X"]]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 200
board[i][j] 为 'X' 或 'O'
二、题解
简而言之就是需要将一个只有'X'和'O'两种字符的一个矩阵里面被字符'X'包围的字符'O'都替换为字符'X'。
方法一
只有被字符'X'包围的字符'O'才需要替换,那么边界出现的'O'是肯定没有被包围的,所以边界上的字符'O'不用替换,并且如果存在与边界的字符'O'相连的'O'也不用替换,相连的就是上下左右的字符相同。简单的想法就是找出所有被包围的字符'O'然后全部替换为字符'X',但是这样可能就比较困难,既然有特殊的情况即边界的字符'O'不用替换,并且只需寻找边界的字符以及可能与边界字符'O'相连的字符,那么我们就可找出所有边界上不用替换的字符'O',最后剩下的其他所有字符'O'都是需要被替换为字符'X'的。具体的我们需要从矩阵的边界元素开始查询字符'O',当查询到一个字符'O'我们就先将其替换为一个临时的字符例如字符'T',然后还需要寻找这个边界字符相连的字符'O',即向其上下左右四个方向扩展搜索字符'O',同样的搜索到一个字符'O'就替换为临时的字符'T',直到超出矩阵边界或者不是字符'O'时结束。搜索完边界之后矩阵中剩余的字符'O'都需要被替换为字符'X',所以直接遍历一次矩阵元素,如果元素等于字符'O'就替换为字符'X',同时之前边界的字符'O'现在都变为字符'T'了,所以当元素等于字符'T'时我们就修改回去为字符'O',最后遍历结束也就完成所有的替换了。
三、代码 方法一 Java代码
class Solution {
int m;
int n;
public void solve(char[][] board) {
m = board.length;
n = board[0].length;
if (m < 3 && n < 3) {
return;
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if ((i == 0 || j == 0 || i == m - 1 || j == n - 1) && board[i][j] == 'O') {
dfs(board, i, j);
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
char c = board[i][j];
if (c == 'O') {
board[i][j] = 'X';
}
if (c == 'T') {
board[i][j] = 'O';
}
}
}
}
private void dfs(char[][] board, int i, int j) {
if (i < 0 || j < 0 || i >= m || j >= n || board[i][j] != 'O') {
return;
}
board[i][j] = 'T';
dfs(board, i - 1, j);
dfs(board, i + 1, j);
dfs(board, i, j - 1);
dfs(board, i, j + 1);
}
}
时间复杂度:O(n^2),需要遍历二维数组的所有元素。
空间复杂度:O(n^2),递归查询边界字符消耗的栈空间。