算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
今天和大家聊的问题叫做 被围绕的区域,我们先来看题面:
https://leetcode-cn.com/problems/surrounded-regions/
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.
题意
给定一个二维的矩阵,包含 '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'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
解题
从边界出发把,先把边界上和O
连通点找到, 把这些变成B
,然后遍历整个board
把O
变成X
, 把B
变成O
如下图所示
思路一: DFS
class Solution {
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public void solve(char[][] board) {
if (board == null || board.length == 0 || board[0] == null || board[0].length == 0) return;
int row = board.length;
int col = board[0].length;
for (int j = 0; j < col; j++) {
// 第一行
if (board[0][j] == 'O') dfs(0, j, board, row, col);
// 最后一行
if (board[row - 1][j] == 'O') dfs(row - 1, j, board, row, col);
}
for (int i = 0; i < row; i++) {
// 第一列
if (board[i][0] == 'O') dfs(i, 0, board, row, col);
// 最后一列
if (board[i][col - 1] == 'O') dfs(i, col - 1, board, row, col);
}
// 转变
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] == 'B') board[i][j] = 'O';
}
}
}
private void dfs(int i, int j, char[][] board, int row, int col) {
board[i][j] = 'B';
for (int[] dir : dirs) {
int tmp_i = dir[0] + i;
int tmp_j = dir[1] + j;
if (tmp_i < 0 || tmp_i >= row || tmp_j < 0 || tmp_j >= col || board[tmp_i][tmp_j] != 'O') continue;
dfs(tmp_i, tmp_j, board, row, col);
}
}
}
思路二: BFS
class Solution {
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
private static class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public void solve(char[][] board) {
if (board == null || board.length == 0 || board[0] == null || board[0].length == 0) return;
int row = board.length;
int col = board[0].length;
for (int j = 0; j < col; j++) {
// 第一行
if (board[0][j] == 'O') bfs(0, j, board, row, col);
// 最后一行
if (board[row - 1][j] == 'O') bfs(row - 1, j, board, row, col);
}
for (int i = 0; i < row; i++) {
// 第一列
if (board[i][0] == 'O') bfs(i, 0, board, row, col);
// 最后一列
if (board[i][col - 1] == 'O') bfs(i, col - 1, board, row, col);
}
// 转变
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] == 'B') board[i][j] = 'O';
}
}
}
private void bfs(int i, int j, char[][] board, int row, int col) {
Deque<Point> queue = new LinkedList<>();
queue.offer(new Point(i, j));
while (!queue.isEmpty()) {
Point tmp = queue.poll();
if (tmp.x >= 0 && tmp.x < row && tmp.y >= 0 && tmp.y < col && board[tmp.x][tmp.y] == 'O') {
board[tmp.x][tmp.y] = 'B';
for (int[] dir : dirs) queue.offer(new Point(tmp.x + dir[0], tmp.y + dir[1]));
}
}
}
}
好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力。
上期推文: