LeetCode-130. 被围绕的区域
-.- 这题不会做,记录下大佬的题解(难度:中等)
一、题目内容
给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。
找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
示例:
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’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
二、题解过程
1、遍历算法分析
本题很明显是要对数组中的所有元素进行遍历,现在的问题是采用何种的遍历算法和遍历方式来帮忙我们找到最快的解题算法。
-
假设我们从开头进行元素的顺序遍历,对字母 O 进行记录则需要构建二维地图,清晰表现出各个字母 O 之间的位置关系,然后进行横向和竖向的遍历,如果能到达边界点,则是没有被包围的,否则就是被字母X包围的O。此种方法因为无法确定当前元素是否能遍历到边界,因此需要先进行记录遍历的元素,再根据遍历的结果重新对元素进行赋值,比较复杂。
-
假设我们先找到边界元素且边界元素为字母O的位置,从边界元素出发进行遍历(横向和纵向遍历),能遍历的字母O元素就是没有被字母X包围的元素。由于是根据结果来找元素因此不用进行二次循环赋值,比较方便。
进行遍历的方法,简单的来说就两种,一种是DFS,一种是BFS,对于任一种算法题来说,能用DFS求解,基本也能用BFS算法求解。
2、解法
2.1 方法一:深度优先搜索
class Solution {
int n, m;
public void solve(char[][] board) {
n = board.length;
if (n == 0) {
return;
}
m = board[0].length;
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] == 'A') {
board[i][j] = 'O';
} else if (board[i][j] == 'O') {
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') {
return;
}
board[x][y] = 'A';
dfs(board, x + 1, y);
dfs(board, x - 1, y);
dfs(board, x, y + 1);
dfs(board, x, y - 1);
}
}
2.2 方法二:广度优先遍历
以下方法中关于当前元素的横向和纵向遍历的方式,采用了一维数组来进行路径的定义,分为x左,x右,y上,y下;
int[] dx = {1, -1, 0, 0};
int[] dy = {0, 0, 1, -1};
for (int i = 0; i < 4; i++) {
int mx = x + dx[i], my = y + dy[i];
if (mx < 0 || my < 0 || mx >= n || my >= m || board[mx][my] != 'O') {
continue;
}
queue.offer(new int[]{mx, my});
}
class Solution {
int[] dx = {1, -1, 0, 0};
int[] dy = {0, 0, 1, -1};
public void solve(char[][] board) {
int n = board.length;
if (n == 0) {
return;
}
int m = board[0].length;
Queue<int[]> queue = new LinkedList<int[]>();
for (int i = 0; i < n; i++) {
if (board[i][0] == 'O') {
queue.offer(new int[]{i, 0});
}
if (board[i][m - 1] == 'O') {
queue.offer(new int[]{i, m - 1});
}
}
for (int i = 1; i < m - 1; i++) {
if (board[0][i] == 'O') {
queue.offer(new int[]{0, i});
}
if (board[n - 1][i] == 'O') {
queue.offer(new int[]{n - 1, i});
}
}
while (!queue.isEmpty()) {
int[] cell = queue.poll();
int x = cell[0], y = cell[1];
board[x][y] = 'A';
for (int i = 0; i < 4; i++) {
int mx = x + dx[i], my = y + dy[i];
if (mx < 0 || my < 0 || mx >= n || my >= m || board[mx][my] != 'O') {
continue;
}
queue.offer(new int[]{mx, my});
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (board[i][j] == 'A') {
board[i][j] = 'O';
} else if (board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
}
}