https://leetcode.com/problems/surrounded-regions/?tab=Description
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.
1 | For example, |
cpp
23ms, 32.42%, October 14, 2016
https://discuss.leetcode.com/topic/17224/a-really-simple-and-readable-c-solution-only-cost-12ms
A really simple and readable C++ solution,only cost 12ms
- First, check the four border of the matrix. If there is a element is ‘O’, alter it and all its neighbor ‘O’ elements to ‘1’.
- Then ,alter all the ‘O’ to ‘X’
- At last,alter all the ‘1’ to ‘O’
1 | For example: |
1 | class Solution { |
https://discuss.leetcode.com/topic/1944/solve-it-using-union-find
Solve it using Union Find
1 | class UF |
Hi. So here is my accepted code using Union Find data structure. The idea comes from the observation that if a region is NOT captured, it is connected to the boundry. So if we connect all the ‘O’ nodes on the boundry to a dummy node, and then connect each ‘O’ node to its neighbour ‘O’ nodes, then we can tell directly whether a ‘O’ node is captured by checking whether it is connected to the dummy node.
For more about Union Find, the first assignment in the algo1 may help:
https://www.coursera.org/course/algs4partI
https://discuss.leetcode.com/topic/1944/solve-it-using-union-find/2
just another version in java:
1 | public class Solution { |
https://discuss.leetcode.com/topic/18706/9-lines-python-148-ms
9 lines, Python 148 ms
Phase 1: “Save” every O-region touching the border, changing its cells to ‘S’.
Phase 2: Change every ‘S’ on the board to ‘O’ and everything else to ‘X’.
1 | def solve(self, board): |
In case you don’t like my last line, you could do this instead:
1 | for row in board: |
https://discuss.leetcode.com/topic/2982/my-bfs-solution-c-28ms
My BFS solution (C++ 28ms)
The algorithm is quite simple: Use BFS starting from ‘O’s on the boundary and mark them as ‘B’, then iterate over the whole board and mark ‘O’ as ‘X’ and ‘B’ as ‘O’.
1 | void bfsBoundary(vector<vector<char> >& board, int w, int l) |
Note that one of the test cases is when the board is empty. So if you don’t check it in your code, you will encounter an run-time error.
Java DFS + boundary cell turning solution, simple and clean code, commented.
1 | public void solve(char[][] board) { |
https://discuss.leetcode.com/topic/6496/my-java-o-n-2-accepted-solution
My Java O(n^2) accepted solution
The idea is pretty simple: a ‘O’ marked cell cannot be captured whether:
- It is in contact with the border of the board or
- It is adjacent to an unflippable cell.
So the algorithm is straightforward:
- Go around the border of the board
- When a ‘O’ cell is found mark it with ‘U’ and perform a DFS on its adjacent cells looking for other ‘O’ marked cells.
- When the entire border is processed scan again the board
- If a cell is marked as ‘O’ it wasn’t connected to unflippable cell. Hence capture it with ‘X’
- If a cell is marked as ‘X’ nothing must be done.
If a cell is marked as ‘U’ mark it as ‘O’ because it was an original ‘O’ marked cell which satisfied one of the above conditions.
On a technical side regarding the code:In the problem statement it’s not specified that the board is rectangular. So different checks must performed when scanning the border.
- Since a pure recursive search causes stack overflow it’s necessary to make the DFS iterative using a stack to simulate recursion.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62public class Solution {
static class Pair {
public int first;
public int second;
public Pair(int f, int s) {
first = f;
second = s;
}
}
public void solve(char[][] board) {
if(board == null || board.length == 0) {
return ;
}
for(int i = 0; i < board[0].length; ++i) {
if(board[0][i] == 'O') {
markUnflippable(board,0,i);
}
}
for(int i = 0; i < board[board.length-1].length; ++i) {
if(board[board.length-1][i] == 'O') {
markUnflippable(board,board.length-1,i);
}
}
for(int i = 0 ; i < board.length; ++i) {
if(board[i][0] == 'O') {
markUnflippable(board,i,0);
}
}
for(int i =0; i < board.length; ++i) {
if(board[i][board[i].length-1] == 'O') {
markUnflippable(board,i,board[i].length-1);
}
}
// modify the board
for(int i = 0; i < board.length; ++i) {
for(int j = 0; j < board[i].length; ++j) {
if(board[i][j] == 'O') {
board[i][j] = 'X';
} else if(board[i][j] == 'U') {
board[i][j] = 'O';
}
}
}
}
public void markUnflippable(char[][] board, int r, int c) {
int[] dirX = {-1,0,1,0};
int[] dirY = {0,1,0,-1};
ArrayDeque<Pair> stack = new ArrayDeque<>();
stack.push(new Pair(r,c));
while(!stack.isEmpty()) {
Pair p = stack.pop();
board[p.first][p.second] = 'U';
for(int i = 0; i < dirX.length; ++i) {
if(p.first + dirX[i] >= 0 && p.first + dirX[i] < board.length && p.second + dirY[i] >= 0 && p.second +dirY[i] < board[p.first + dirX[i]].length && board[p.first+dirX[i]][p.second+dirY[i]] == 'O') {
stack.push(new Pair(p.first+dirX[i],p.second+dirY[i]));
}
}
}
}