LeetCode 130. 被围绕的区域 Surrounded Regions(Java)
##DFS##, ##BFS##, ##Union Find##
泛洪算法 O ( n 2 ) O(n^2) O(n2)
采用逆向思维,将所有边界上的O
采用Flood Fill算法标记其连通域,并做标记#
,
全图遍历完后,对于board
中所有字符不为#
的字符,如果为O
,即代表不与边界的O
(遍历后改为#
)相连,因此被X
包围,改为X
采用int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1}
标记即将要遍历的方向
class Solution {
int n, m;
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
public void solve(char[][] board) {
n = board.length;
if (n == 0) return;
m = board[0].length;
for (int i = 0; i < m; i ++) {
if (board[0][i] == 'O') {
dfs(board, 0, i);
}
if (board[n - 1][i] == 'O') {
dfs(board, n - 1, i);
}
}
for (int i = 0; i < n; i ++) {
if (board[i][0] == 'O') {
dfs(board, i, 0);
}
if (board[i][m - 1] == 'O') {
dfs(board, i, m - 1);
}
}
for (int i = 0; i < n; i ++) {
for (int j = 0; j < m; j ++) {
if (board[i][j] == '#') {
board[i][j] = 'O';
} else {
board[i][j] = 'X';
}
}
}
}
public void dfs(char[][] board, int x, int y) {
board[x][y] = '#';
for (int i = 0; i < 4; i ++) {
int xx = x + dx[i];
int yy = y + dy[i];
if (xx >= 0 && xx < n && yy >= 0 && yy < m && board[xx][yy] == 'O') {
dfs(board, xx, yy);
}
}
}
}
并查集
将边界中的字符为O
的区域与dummy
结点相连,表示为不被X
包围的字符,
并查集中结点数量应该为rows * cols + 1
,多出的一个为dummy
结点,dummy = rows * cols
遍历所有字符,如果字符board[i][j] == O
则,与其上下左右四个方向的O
字符向联通
最后遍历整个图形,所有与dummy
结点相连的O
结点都不是被包围的结点
class Solution {
public class UnionFind {
int[] p = new int[100010];
int n;
public void init(int n) {
this.n = n;
for (int i = 0; i < n; i ++) {
p[i] = i;
}
}
public int find(int x) {
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
public void union(int x, int y) {
p[find(y)] = find(x);
}
public boolean isConnected(int x, int y) {
return find(x) == find(y);
}
}
int n, m;
public void solve(char[][] board) {
n = board.length;
if (n == 0) return;
m = board[0].length;
UnionFind uf = new UnionFind();
uf.init(n * m + 1);
int dummy = n * m;
for (int i = 0; i < n; i ++) {
for (int j = 0; j < m; j ++) {
if (board[i][j] == 'O') {
if (i == 0 || i == n - 1 || j == 0 || j == m - 1) {
uf.union(node(i, j), dummy);
} else {
if (i - 1 >= 0 && board[i - 1][j] == 'O') {
uf.union(node(i - 1, j), node(i, j));
}
if (i + 1 < n && board[i + 1][j] == 'O') {
uf.union(node(i + 1, j), node(i, j));
}
if (j - 1 >= 0 && board[i][j - 1] == 'O') {
uf.union(node(i, j - 1), node(i, j));
}
if (j + 1 < m && board[i][j + 1] == 'O') {
uf.union(node(i, j + 1), node(i, j));
}
}
}
}
}
for (int i = 0; i < n; i ++) {
for (int j = 0; j < m; j ++) {
if (uf.isConnected(node(i, j), dummy)) {
board[i][j] = 'O';
} else {
board[i][j] = 'X';
}
}
}
}
public int node(int x, int y) {
return x * m + y;
}
}