Surrounded Regions
Question
Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'.
A region is captured by flipping all 'O''s into 'X''s in that surrounded region.
Example
X X X X
X O O X
X X O X
X O X X
After capture all regions surrounded by 'X', the board should be:
X X X X
X X X X
X X X X
X O X X
Tags
Breadth First Search Union Find
Related Problems
Hard Number of Islands II Easy Number of Islands
Analysis
本题也是一个多解的问题。
一种比较巧妙的思路是从边缘的'O'出发,通过DFS,所有能够遍历的'O'都可以暂时被标记为'#',那么剩下未能被标记的'O'说明被surrounded,需要在遍历结束之后全部转为'X'。(用DFS或者BFS要警惕栈溢出)
另一种方法是用Union Find,将与边缘相连通的'O'全部union到一个dummy node(也可以用hasEdge[]来存储,不过内存占用更多), 最终将没有和这个dummy node是一个component的'O'点全部标记为'X'。
Solution
DFS - (7ms AC 42.74%)
class Solution {
public void solve(char[][] board) {
if (board == null || board.length == 0 || board[0].length == 0) return;
int m = board.length;
int n = board[0].length;
// Marking 'O' on the boundary and connected as '*'
for (int i = 0; i < m; i++) {
if (board[i][0] == 'O') {
marking(board, i, 0);
}
if (board[i][n - 1] == 'O') {
marking(board, i, n - 1);
}
}
for (int j = 0; j < n; j++) {
if (board[0][j] == 'O') {
marking(board, 0, j);
}
if (board[m - 1][j] == 'O') {
marking(board, m - 1, j);
}
}
// Replacing 'O' as 'X'
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
// Replacing '*' as 'X'
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == '*') {
board[i][j] = 'O';
}
}
}
}
// DFS marking 'O' as '*'
private void marking (char[][] board, int x, int y) {
int[] dx = {0, 1, 0, -1};
int[] dy = {1, 0, -1, 0};
int nx, ny;
if (board[x][y] == 'O') {
board[x][y] = '*';
for (int i = 0; i < 4; i++) {
nx = x + dx[i];
ny = y + dy[i];
if (nx >= 0 && ny >= 0 && nx < board.length && ny < board[0].length) {
marking(board, nx, ny);
}
}
}
}
}
DFS - (4ms AC 100%)
class Solution {
public void solve(char[][] board) {
if (board.length < 1 || board[0].length < 1)
return;
for (int i = 0; i < board.length; i++) {
if (board[i][0] != 'X');
dfsmarker(i, 0, board);
}
for (int i = 0; i < board.length; i++) {
if (board[i][board[0].length - 1] != 'X')
dfsmarker(i, board[0].length - 1, board);
}
for (int j = 0; j < board[0].length; j++) {
if (board[0][j] != 'X');
dfsmarker(0, j, board);
}
for (int j = 0; j < board[0].length; j++) {
if (board[board.length - 1][j] != 'X')
dfsmarker(board.length - 1, j, board);
}
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
//System.out.println(marker[i][j]);
if (board[i][j] == 'M')
board[i][j] = 'O';
else
board[i][j] = 'X';
}
}
//System.out.println(marker[1][1]);
return;
}
public void dfsmarker(int i, int j, char[][] board) {
if (board[i][j] == 'M' || board[i][j] != 'O')
return;
board[i][j] = 'M';
if (i > 0)
dfsmarker(i - 1, j, board);
if (j > 0)
dfsmarker(i, j - 1, board);
if (i < board.length - 1)
dfsmarker(i + 1, j, board);
if (j < board[0].length - 1)
dfsmarker(i, j + 1, board);
}
}
DFS - Cleaner Version (6ms 59.18%)
class Solution {
public void solve(char[][] board) {
if (board.length == 0 || board[0].length == 0) return;
if (board.length < 3 || board[0].length < 3) return;
int m = board.length;
int n = board[0].length;
for (int i = 0; i < m; i++) {
if (board[i][0] == 'O') helper(board, i, 0);
if (board[i][n - 1] == 'O') helper(board, i, n - 1);
}
for (int j = 1; j < n - 1; j++) {
if (board[0][j] == 'O') helper(board, 0, j);
if (board[m - 1][j] == 'O') helper(board, m - 1, j);
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'O') board[i][j] = 'X';
if (board[i][j] == '*') board[i][j] = 'O';
}
}
}
private void helper(char[][] board, int r, int c) {
if (r < 0 || c < 0 || r > board.length - 1 || c > board[0].length - 1 || board[r][c] != 'O') return;
board[r][c] = '*';
helper(board, r + 1, c);
helper(board, r - 1, c);
helper(board, r, c + 1);
helper(board, r, c - 1);
}
}
Union Find (20 ms 14.75% AC)
class UnionFind {
private int[] id;
private int[] size;
public UnionFind(int n) {
id = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
id[i] = i;
size[i] = 1;
}
}
public int find(int i) {
while (i != id[i]) {
id[i] = id[id[i]];
i = id[i];
}
return i;
}
public void union(int x, int y) {
int i = find(x);
int j = find(y);
if (i == j) {
return;
}
if (size[i] < size[j]) {
id[i] = j;
size[j] += size[i];
} else {
id[j] = i;
size[i] += size[j];
}
}
public boolean connected(int x, int y) {
return find(x) == find(y);
}
}
public class Solution {
private boolean isEdge(int M, int N, int i, int j) {
return (i == 0 || i == M - 1 || j == 0 || j == N - 1);
}
private boolean insideBoard(int M, int N, int i, int j) {
return (i < M && i >= 0 && j < N && j >= 0);
}
/**
* @param board a 2D board containing 'X' and 'O'
* @return void
*/
public void surroundedRegions(char[][] board) {
if (board == null || board.length == 0 || board[0].length == 0) {
return;
}
int M = board.length;
int N = board[0].length;
int[] dirX = {0, 0, -1, 1};
int[] dirY = {-1, 1, 0, 0};
UnionFind uf = new UnionFind(M * N + 1);
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
if (board[i][j] == 'O') {
if (isEdge(M, N, i, j)) {
uf.union(i * N + j, M * N);
} else {
for (int k = 0; k < 4; k++) {
int x = i + dirX[k];
int y = j + dirY[k];
if (insideBoard(M, N, x, y) && board[x][y] == 'O') {
uf.union(i * N + j, x * N + y);
}
}
}
}
}
}
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
if (!uf.connected(i * N + j, M * N)) {
board[i][j] = 'X';
}
}
}
}
}
Reference
Last updated