Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given an m x n matrix board containing letters 'X' and 'O', capture regions that are surrounded:
'O' cell.'O' cells in that region are on the edge of the board. Such regions are completely enclosed by 'X' cells.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"]]
Constraints:
m == board.lengthn == board[i].length1 <= m, n <= 200board[i][j] is 'X' or 'O'.Problem summary: 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: A region is surrounded if none of the 'O' cells in that region are on the edge of the board. Such regions are completely enclosed by 'X' cells. 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Union-Find
[["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
[["X"]]
number-of-islands)walls-and-gates)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #130: Surrounded Regions
class Solution {
private final int[] dirs = {-1, 0, 1, 0, -1};
private char[][] board;
private int m;
private int n;
public void solve(char[][] board) {
m = board.length;
n = board[0].length;
this.board = board;
for (int i = 0; i < m; ++i) {
dfs(i, 0);
dfs(i, n - 1);
}
for (int j = 0; j < n; ++j) {
dfs(0, j);
dfs(m - 1, j);
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == '.') {
board[i][j] = 'O';
} else if (board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
}
private void dfs(int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'O') {
return;
}
board[i][j] = '.';
for (int k = 0; k < 4; ++k) {
dfs(i + dirs[k], j + dirs[k + 1]);
}
}
}
// Accepted solution for LeetCode #130: Surrounded Regions
func solve(board [][]byte) {
m, n := len(board), len(board[0])
dirs := [5]int{-1, 0, 1, 0, -1}
var dfs func(i, j int)
dfs = func(i, j int) {
if i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'O' {
return
}
board[i][j] = '.'
for k := 0; k < 4; k++ {
dfs(i+dirs[k], j+dirs[k+1])
}
}
for i := 0; i < m; i++ {
dfs(i, 0)
dfs(i, n-1)
}
for j := 0; j < n; j++ {
dfs(0, j)
dfs(m-1, j)
}
for i, row := range board {
for j, c := range row {
if c == '.' {
board[i][j] = 'O'
} else if c == 'O' {
board[i][j] = 'X'
}
}
}
}
# Accepted solution for LeetCode #130: Surrounded Regions
class Solution:
def solve(self, board: List[List[str]]) -> None:
def dfs(i: int, j: int):
if not (0 <= i < m and 0 <= j < n and board[i][j] == "O"):
return
board[i][j] = "."
for a, b in pairwise((-1, 0, 1, 0, -1)):
dfs(i + a, j + b)
m, n = len(board), len(board[0])
for i in range(m):
dfs(i, 0)
dfs(i, n - 1)
for j in range(n):
dfs(0, j)
dfs(m - 1, j)
for i in range(m):
for j in range(n):
if board[i][j] == ".":
board[i][j] = "O"
elif board[i][j] == "O":
board[i][j] = "X"
// Accepted solution for LeetCode #130: Surrounded Regions
impl Solution {
pub fn solve(board: &mut Vec<Vec<char>>) {
let m = board.len();
let n = board[0].len();
let dirs = vec![-1, 0, 1, 0, -1];
fn dfs(
board: &mut Vec<Vec<char>>,
i: usize,
j: usize,
dirs: &Vec<i32>,
m: usize,
n: usize,
) {
if i >= 0 && i < m && j >= 0 && j < n && board[i][j] == 'O' {
board[i][j] = '.';
for k in 0..4 {
dfs(
board,
((i as i32) + dirs[k]) as usize,
((j as i32) + dirs[k + 1]) as usize,
dirs,
m,
n,
);
}
}
}
for i in 0..m {
dfs(board, i, 0, &dirs, m, n);
dfs(board, i, n - 1, &dirs, m, n);
}
for j in 0..n {
dfs(board, 0, j, &dirs, m, n);
dfs(board, m - 1, j, &dirs, m, n);
}
for i in 0..m {
for j in 0..n {
if board[i][j] == '.' {
board[i][j] = 'O';
} else if board[i][j] == 'O' {
board[i][j] = 'X';
}
}
}
}
}
// Accepted solution for LeetCode #130: Surrounded Regions
function solve(board: string[][]): void {
const m = board.length;
const n = board[0].length;
const dirs: number[] = [-1, 0, 1, 0, -1];
const dfs = (i: number, j: number): void => {
if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] !== 'O') {
return;
}
board[i][j] = '.';
for (let k = 0; k < 4; ++k) {
dfs(i + dirs[k], j + dirs[k + 1]);
}
};
for (let i = 0; i < m; ++i) {
dfs(i, 0);
dfs(i, n - 1);
}
for (let j = 0; j < n; ++j) {
dfs(0, j);
dfs(m - 1, j);
}
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
if (board[i][j] === '.') {
board[i][j] = 'O';
} else if (board[i][j] === 'O') {
board[i][j] = 'X';
}
}
}
}
Use this to step through a reusable interview workflow for this problem.
Track components with a list or adjacency matrix. Each union operation may need to update all n elements’ component labels, giving O(n) per union. For n union operations total: O(n²). Find is O(1) with direct lookup, but union dominates.
With path compression and union by rank, each find/union operation takes O(α(n)) amortized time, where α is the inverse Ackermann function — effectively constant. Space is O(n) for the parent and rank arrays. For m operations on n elements: O(m × α(n)) total.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.