Skip to main content

Breadth First Search

Surrounded Regions

Problem Statement

Given an m x n matrix board containing 'X' and 'O'capture all regions that are 4-directionally surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

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: Notice that an 'O' should not be flipped if:
- It is on the border, or
- It is adjacent to an 'O' that should not be flipped.
The bottom 'O' is on the border, so it is not flipped.
The other three 'O' form a surrounded region, so they are flipped.

Example 2

Input: board = [["X"]]
Output: [["X"]]

Try here before watching the video.

Video Explanation

Java Code

import java.util.LinkedList;
import java.util.Queue;

class Node {
    int row, col;
    public Node(int row, int col) {
        this.row = row;
        this.col = col;
    }
}

class Solution {

    int[][] directions = new int[][]{{-1, 0}, {0, -1}, {0, 1}, {1, 0}};

    private boolean isValidCell(int row, int col, int rows, int cols) {
        if(row >= 0 && row < rows && col >= 0 && col < cols) 
            return true;
        else 
            return false;
    }

    public void solve(char[][] board) {
        
        int rows = board.length;
        int cols = board[0].length;
        
        Queue<Node> queue = new LinkedList<>();
        for(int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                if(i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {
                    if(board[i][j] == 'O') {
                        queue.add(new Node(i, j));
                        board[i][j] = 'V';
                    }
                }
            }
        }

        while(!queue.isEmpty()) {
            Node node = queue.poll();

            for(int[] direction : directions) {
                int newRow = node.row + direction[0];
                int newCol = node.col + direction[1];
                if(isValidCell(newRow, newCol, rows, cols) && board[newRow][newCol] == 'O') {
                    queue.add(new Node(newRow, newCol));
                    board[newRow][newCol] = 'V';
                }
            }
        }

        for(int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                if(board[i][j] == 'V') {
                    board[i][j] = 'O';
                } else {
                    board[i][j] = 'X';
                }
            }
        }

    }
}

C++ Code

#include<bits/stdc++.h>
using namespace std;

class Node {
public:
    int row, col;
    Node(int row, int col) {
        this->row = row;
        this->col = col;
    }
};

class Solution {
public:

    vector<vector<int>> directions = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};

    bool isValidCell(int row, int col, int rows, int cols) {
        if(row >= 0 && row < rows && col >= 0 && col < cols) 
            return true;
        else 
            return false;
    }

    void solve(vector<vector<char>>& board) {

        int rows = board.size();
        int cols = board[0].size();
        
        queue<Node> queue;

        for(int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                if(i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {
                    if(board[i][j] == 'O') {
                        queue.push(Node(i, j));
                        board[i][j] = 'V';
                    }
                }
            }
        }

        while(!queue.empty()) {
            Node node = queue.front();
            queue.pop();

            for(auto& direction : directions) {
                int newRow = node.row + direction[0];
                int newCol = node.col + direction[1];
                if(isValidCell(newRow, newCol, rows, cols) && board[newRow][newCol] == 'O') {
                    queue.push(Node(newRow, newCol));
                    board[newRow][newCol] = 'V';
                }
            }
        }

        for(int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                if(board[i][j] == 'V') {
                    board[i][j] = 'O';
                } else {
                    board[i][j] = 'X';
                }
            }
        }
        
    }
};

Python Code

from typing import List
from collections import deque

class Solution:
    def solve(self, board: List[List[str]]) -> None:

        rows, cols = len(board), len(board[0])
        distances = [(-1, 0), (0, -1), (0, 1), (1, 0)]

        def is_valid_cell(row, col):
            return 0 <= row < rows and 0 <= col < cols
        
        queue = deque()

        for i in range(rows):
            for j in range(cols):
                if i == 0 or i == rows - 1 or j == 0 or j == cols - 1:
                    if board[i][j] == 'O':
                        queue.append((i, j))
                        board[i][j] = 'V'
                    
        while queue:
            row, col = queue.popleft()

            for direction in distances:
                new_row, new_col = row + direction[0], col + direction[1]
                if is_valid_cell(new_row, new_col) and board[new_row][new_col] == 'O':
                    queue.append((new_row, new_col))
                    board[new_row][new_col] = 'V'

        
        for i in range(rows):
            for j in range(cols):
                if board[i][j] == 'V':
                    board[i][j] = 'O'
                elif board[i][j] == 'O':
                    board[i][j] = 'X'

Javascript Code

class Node {
    constructor(row, col) {
        this.row = row;
        this.col = col;
    }
}

var solve = function(board) {
    const directions = [[-1, 0], [0, -1], [0, 1], [1, 0]];

    const isValidCell = (row, col, rows, cols) => {
        return row >= 0 && row < rows && col >= 0 && col < cols;
    };

    const rows = board.length;
    const cols = board[0].length;
    const queue = [];

    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
            if (i === 0 || i === rows - 1 || j === 0 || j === cols - 1) {
                if (board[i][j] === 'O') {
                    queue.push(new Node(i, j));
                    board[i][j] = 'V';
                }
            }
        }
    }

    while (queue.length > 0) {
        const node = queue.shift();

        for (const direction of directions) {
            const newRow = node.row + direction[0];
            const newCol = node.col + direction[1];

            if (isValidCell(newRow, newCol, rows, cols) && board[newRow][newCol] === 'O') {
                queue.push(new Node(newRow, newCol));
                board[newRow][newCol] = 'V';
            }
        }
    }

    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
            if (board[i][j] === 'V') {
                board[i][j] = 'O';
            } else {
                board[i][j] = 'X';
            }
        }
    }
};

Go Code

type Node struct {
    Row int
    Col int
}

var directions = [][]int{{-1, 0}, {0, -1}, {0, 1}, {1, 0}}

func isValidCell(row, col, rows, cols int) bool {
    return row >= 0 && row < rows && col >= 0 && col < cols
}

func solve(board [][]byte) {
    rows := len(board)
    cols := len(board[0])
    queue := make([]Node, 0)

    for i := 0; i < rows; i++ {
        for j := 0; j < cols; j++ {
            if i == 0 || i == rows-1 || j == 0 || j == cols-1 {
                if board[i][j] == 'O' {
                    queue = append(queue, Node{i, j})
                    board[i][j] = 'V'
                }
            }
        }
    }

    for len(queue) > 0 {
        node := queue[0]
        queue = queue[1:]

        for _, direction := range directions {
            newRow := node.Row + direction[0]
            newCol := node.Col + direction[1]

            if isValidCell(newRow, newCol, rows, cols) && board[newRow][newCol] == 'O' {
                queue = append(queue, Node{newRow, newCol})
                board[newRow][newCol] = 'V'
            }
        }
    }

    for i := 0; i < rows; i++ {
        for j := 0; j < cols; j++ {
            if board[i][j] == 'V' {
                board[i][j] = 'O'
            } else {
                board[i][j] = 'X'
            }
        }
    }
}

Complexity Analysis

Time Complexity: O(N), where N is the number of cells in the board.
Space Complexity: O(N), where N is the number of cells in the board.