Skip to main content

Surrounded Region (DFS)

Problem Statement:​

You are given an m x n matrix board containing letters 'X' and 'O', capture regions that are surrounded:

  • Connect: A cell is connected to adjacent cells horizontally or vertically.
  • Region: To form a region connect every 'O' cell.
  • Surround: The region is surrounded with 'X' cells if you can connect the region with 'X' cells and none of the region cells are on the edge of the board.

To capture a surrounded region, replace all 'O's with 'X's in-place within the original board. You do not need to return anything.

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"]]

Explanation:

In the above diagram, the bottom region is not captured because it is on the edge of the board and cannot be surrounded.

Example 2:

Input: board = [["X"]]

Output: [["X"]]

  • Example:


class Solution {
public:
// Perform DFS to mark all 'O's connected to boundary 'O's
void dfs(int x, int y, int n, int m, vector<vector<int>> &visited, int dx[], int dy[], vector<vector<char>> &board) {
visited[x][y] = 1;

for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];

// Check bounds and if the cell is unvisited and has 'O'
if (newX >= 0 && newX < n && newY >= 0 && newY < m &&
!visited[newX][newY] && board[newX][newY] == 'O') {
dfs(newX, newY, n, m, visited, dx, dy, board);
}
}
}

void solve(vector<vector<char>>& board) {
int n = board.size();
int m = board[0].size();

vector<vector<int>> visited(n, vector<int>(m, 0));
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

// Check first and last row
for (int j = 0; j < m; j++) {
if (!visited[0][j] && board[0][j] == 'O') {
dfs(0, j, n, m, visited, dx, dy, board);
}
if (!visited[n - 1][j] && board[n - 1][j] == 'O') {
dfs(n - 1, j, n, m, visited, dx, dy, board);
}
}

// Check first and last column
for (int i = 0; i < n; i++) {
if (!visited[i][0] && board[i][0] == 'O') {
dfs(i, 0, n, m, visited, dx, dy, board);
}
if (!visited[i][m - 1] && board[i][m - 1] == 'O') {
dfs(i, m - 1, n, m, visited, dx, dy, board);
}
}

// Flip all unvisited 'O's to 'X'
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (!visited[i][j] && board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
}
};


📝 How It Works​

  • This is the "Surrounded Regions" problem where we want to flip all 'O's that are not connected to boundary 'O's into 'X's.

  • We:

    1. Use DFS starting from all boundary 'O's to mark connected 'O's as visited.
    2. Traverse the entire board again and convert all unvisited 'O's to 'X'.
  • Important Note:

    The original code had this subtle bug:

    vector<vector<char>> board was passed by value to DFS.

    This means updates in DFS didn’t reflect back.

    It must be vector<vector<char>> &board (by reference).


🧩 Key Formula / Recurrence​

  • No classic recurrence. It’s a plain DFS grid traversal.

  • Recurrence relationship for DFS:

    dfs(x, y) = dfs(x+1, y) + dfs(x-1, y) + dfs(x, y+1) + dfs(x, y-1)


⏱️ Time & Space Complexity​

ComplexityValue
TimeO(N × M) — Every cell is visited at most once
SpaceO(N × M) — For visited matrix and call stack in worst case (recursion depth)

⚠️ Edge Cases​

  • Empty board or board.size() == 0.
  • All cells are 'X'.
  • All cells are 'O' but on the boundary only (shouldn’t flip anything).
  • Single row or single column grids.

💡 Other Approaches​

  • BFS instead of DFS — Similar logic, just use a queue.
  • In-place marking using temporary character — Instead of extra visited array, temporarily mark boundary-connected 'O's with something like '#', then revert them later.

  • LeetCode 200: Number of Islands
  • LeetCode 695: Max Area of Island
  • LeetCode 130: Surrounded Regions (exact same problem)
  • LeetCode 417: Pacific Atlantic Water Flow

🛠️ Other Notes​

  • Real-world analogy:

    Think of 'O' as water and 'X' as land.

    We want to drain ponds that are not touching the sea (boundary).

  • Always prefer passing large structures like vector<vector<>> by reference to avoid unnecessary copying in DFS or BFS problems.

🚀 Level Up Your Engineering Mindset

Never Study in Isolation. Join Binary Dose.

Connect with fellow engineers, clear conceptual doubts, and get 2 visual breakdowns & engineering mental models daily across our community channels.

Discord
Official Hub

Discord Community

Start at #welcome-and-rules, say hello in #general-chat, clear doubts, and collaborate with engineers worldwide.

Join Discord Server→
⚡
Daily Knowledge Drops

Daily Visual Deep-Dives

Bite-sized system design schematics, core OS internals, and DSA intuition served right into your feeds every single day.

💡Have handwritten notes, cheat-sheets, or want to publish a technical article?
Learn How to Contribute→