Surrounded Regions
Surrounded Regions is a medium graphs problem solved with the dfs - complement trick pattern.
The best approach, optimal (dfs from the border, the complement trick), runs in O(m · n) time and O(m · n) space.
Below are 2 approaches in Java, from check each region separately up.
Problem
In a board of 'X' and 'O', capture every region of O that is completely surrounded by X by flipping it to X. A region connected to the border is not surrounded and stays.
Examples
Example 1
- Input
board = [[X,X,X,X],[X,O,O,X],[X,X,O,X],[X,O,X,X]]- Output
[[X,X,X,X],[X,X,X,X],[X,X,X,X],[X,O,X,X]]- Why
- The bottom O touches the border, so it survives.
Example 2
- Input
board = [[O]]- Output
[[O]]
Constraints
1 <= m, n <= 200; cells are 'X' or 'O'.
Animated walkthrough
A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.
Concepts first, then the problem and every approach, step by step.
Space to play or pause · ← → to jump a step · click or drag the bar to seek
Solutions
Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.
| Approach | Time | Space |
|---|---|---|
| Check each region separately | O(m · n) | O(m · n) |
| Optimal (DFS from the border, the complement trick) | O(m · n) | O(m · n) |
1Check each region separately
O(m · n)O(m · n)For each unvisited O, BFS its whole region, noting whether it touches the border. If not, flip the region.
- BFS the region, collecting cells and a touchesBorder flag.
- If !touchesBorder, flip every collected cell to X.
class Solution {
public void solve(char[][] board) {
int m = board.length, n = board[0].length;
boolean[][] seen = new boolean[m][n];
int[][] dirs = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
if (board[i][j] != 'O' || seen[i][j]) continue;
List<int[]> region = new ArrayList<>();
boolean border = false;
Queue<int[]> q = new ArrayDeque<>();
q.add(new int[] { i, j });
seen[i][j] = true;
while (!q.isEmpty()) {
int[] c = q.poll();
region.add(c);
if (c[0] == 0 || c[1] == 0 || c[0] == m - 1 || c[1] == n - 1) border = true;
for (int[] d : dirs) {
int r = c[0] + d[0], k = c[1] + d[1];
if (r >= 0 && k >= 0 && r < m && k < n && board[r][k] == 'O' && !seen[r][k]) {
seen[r][k] = true;
q.add(new int[] { r, k });
}
}
}
if (!border) for (int[] c : region) board[c[0]][c[1]] = 'X';
}
}
}2Optimal (DFS from the border, the complement trick)
O(m · n)O(m · n)Recursion depth in the worst case.Start a DFS from every border O and mark everything it reaches as safe ('#'). Then scan: remaining O cells are surrounded and become X, and '#' cells turn back into O.
- For each border cell that is O, mark(r, c) → '#'.
- Scan all cells: O → X, # → O.
class Solution {
public void solve(char[][] board) {
int m = board.length, n = board[0].length;
for (int i = 0; i < m; i++) { mark(board, i, 0); mark(board, i, n - 1); }
for (int j = 0; j < n; j++) { mark(board, 0, j); mark(board, m - 1, j); }
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
board[i][j] = board[i][j] == '#' ? 'O' : 'X';
}
private void mark(char[][] b, int r, int c) {
if (r < 0 || c < 0 || r >= b.length || c >= b[0].length || b[r][c] != 'O') return;
b[r][c] = '#';
mark(b, r + 1, c);
mark(b, r - 1, c);
mark(b, r, c + 1);
mark(b, r, c - 1);
}
}Edge cases to test
- Every O connected to the border
- Single row or column
Hints
Hint 1
It is hard to prove a region is surrounded, but easy to find regions that are not: they touch the border. Mark those, then flip everything else (the complement).
FAQ
What is the best time complexity for Surrounded Regions?
Optimal (DFS from the border, the complement trick) runs in O(m · n) time and O(m · n) extra space.
Which pattern does Surrounded Regions use?
It is a graphs problem that uses the dfs - complement trick pattern.
Is there a brute force solution for Surrounded Regions?
Yes. Check each region separately takes O(m · n) time and O(m · n) space. For each unvisited O, BFS its whole region, noting whether it touches the border.
Which edge cases should I test for Surrounded Regions?
Every O connected to the border; Single row or column.