Surrounded Regions

Medium Graphs DFS - Complement Trick Original on LeetCode

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.

ApproachTimeSpace
Check each region separatelyO(m · n)O(m · n)
Optimal (DFS from the border, the complement trick)O(m · n)O(m · n)

1Check each region separately

TimeO(m · n)
SpaceO(m · n)

For each unvisited O, BFS its whole region, noting whether it touches the border. If not, flip the region.

  1. BFS the region, collecting cells and a touchesBorder flag.
  2. If !touchesBorder, flip every collected cell to X.
Java
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)

TimeO(m · n)
SpaceO(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.

  1. For each border cell that is O, mark(r, c) → '#'.
  2. Scan all cells: O → X, # → O.
Java
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.