Given a matrix grid[ ][ ] where each cell contains either 'O' or 'X'. We have to replace all the ‘O’s with ‘X’s if they are surrounded by ‘X’s on all sides.
An 'O' is considered surrounded if it cannot reach the boundary of the matrix by moving up, down, left, or right through adjacent 'O' cells.
Examples:
Input: grid[][] = [['X', 'O', 'X', 'X', 'X', 'X'],
['X', 'O', 'X', 'X', 'O', 'X'],
['X', 'X', 'X', 'O', 'O', 'X'],
['O', 'X', 'X', 'X', 'X', 'X'],
['X', 'X', 'X', 'O', 'X', 'O'],
['O', 'O', 'X', 'O', 'O', 'O']]Output: [['X', 'O', 'X', 'X', 'X', 'X'],
['X', 'O', 'X', 'X', 'X', 'X'],
['X', 'X', 'X', 'X', 'X', 'X'],
['O', 'X', 'X', 'X', 'X', 'X'],
['X', 'X', 'X', 'O', 'X', 'O'],
['O', 'O', 'X', 'O', 'O', 'O']]Explanation: The 'O's at positions (1,4), (2,3), and (2,4) are completely surrounded by 'X' on all sides, so they are replaced with 'X'. All other 'O's remain unchanged because they are connected to the boundary ‘O’s,
Input: grid[][] = [['X', 'X', 'X', 'X']
['X', 'O', 'X', 'X']
['X', 'O', 'O', 'X']
['X', 'O', 'X', 'X']
['X', 'X', 'O', 'O']]Output: [['X', 'X', 'X', 'X']
['X', 'X', 'X', 'X']
['X', 'X', 'X', 'X']
['X', 'X', 'X', 'X']
['X', 'X', 'O', 'O']]Explanation: The 'O's at positions (1,1), (2,1), (2,2), (3,1) is fully surrounded by
'X'and is converted to'X'; the'O's at (4,2) and (4,3) remain because they touch the matrix boundary.
[Approach] Using Flood Fill Algorithm
The main idea is to use the Flood-Fill algorithm. The key difference here is that an 'O' is not replaced by an 'X' if it is part of a region connected to the boundary. To achieve this, we temporarily mark all the 'O's that are connected to any boundary 'O' using any traversal algorithm. After marking, we traverse the entire grid — any 'O' that is not marked is completely surrounded and can be safely converted into 'X'.
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
// A recursive function to replace previous value at '(x, y)'
// and all surrounding values of (x, y) with new value
void fillUtil(vector<vector<char>>& grid,
int x, int y, char prevV, char newV)
{
int m = grid.size();
int n = grid[0].size();
// Base cases
if (x < 0 || x >= m || y < 0 || y >= n)
return;
if (grid[x][y] != prevV)
return;
// Replace current cell
grid[x][y] = newV;
// Recur for 4 directions
fillUtil(grid, x+1, y, prevV, newV);
fillUtil(grid, x-1, y, prevV, newV);
fillUtil(grid, x, y+1, prevV, newV);
fillUtil(grid, x, y-1, prevV, newV);
}
void fill(vector<vector<char>>& grid)
{
int m = grid.size();
int n = grid[0].size();
// Replace all 'O' with '-'
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 'O') {
grid[i][j] = '-';
}
}
}
// Flood fill for '-' on edges
for (int i = 0; i < m; i++) {
if (grid[i][0] == '-') fillUtil(grid, i, 0, '-', 'O');
if (grid[i][n - 1] == '-') fillUtil(grid, i, n - 1, '-', 'O');
}
for (int j = 0; j < n; j++) {
if (grid[0][j] == '-') fillUtil(grid, 0, j, '-', 'O');
if (grid[m - 1][j] == '-') fillUtil(grid, m - 1, j, '-', 'O');
}
// Replace remaining '-' with 'X'
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '-') {
grid[i][j] = 'X';
}
}
}
}
//Driver Code Starts
int main()
{
vector<vector<char>> grid = {
{'X', 'O', 'X', 'O', 'X', 'X'},
{'X', 'O', 'X', 'X', 'O', 'X'},
{'X', 'X', 'X', 'O', 'X', 'X'},
{'O', 'X', 'X', 'X', 'X', 'X'},
{'X', 'X', 'X', 'O', 'X', 'O'},
{'O', 'O', 'X', 'O', 'O', 'O'},
};
fill(grid);
for (auto& row : grid) {
for (char c : row) {
cout << c << " ";
}
cout << endl;
}
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
public class GFG {
//Driver Code Ends
// A recursive function to replace previous value at '(x, y)'
// and all surrounding values of (x, y) with new value
static void fillUtil(char[][] grid,
int x, int y, char prevV, char newV)
{
int m = grid.length;
int n = grid[0].length;
// Base cases
if (x < 0 || x >= m || y < 0 || y >= n)
return;
if (grid[x][y] != prevV)
return;
// Replace current cell
grid[x][y] = newV;
// Recur for 4 directions
fillUtil(grid, x+1, y, prevV, newV);
fillUtil(grid, x-1, y, prevV, newV);
fillUtil(grid, x, y+1, prevV, newV);
fillUtil(grid, x, y-1, prevV, newV);
}
static void fill(char[][] grid)
{
int m = grid.length;
int n = grid[0].length;
// Replace all 'O' with '-'
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 'O') {
grid[i][j] = '-';
}
}
}
// Flood fill for '-' on edges
for (int i = 0; i < m; i++) {
if (grid[i][0] == '-') fillUtil(grid, i, 0, '-', 'O');
if (grid[i][n - 1] == '-') fillUtil(grid, i, n - 1, '-', 'O');
}
for (int j = 0; j < n; j++) {
if (grid[0][j] == '-') fillUtil(grid, 0, j, '-', 'O');
if (grid[m - 1][j] == '-') fillUtil(grid, m - 1, j, '-', 'O');
}
// Replace remaining '-' with 'X'
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '-') {
grid[i][j] = 'X';
}
}
}
}
//Driver Code Starts
public static void main(String[] args)
{
char[][] grid = {
{'X', 'O', 'X', 'O', 'X', 'X'},
{'X', 'O', 'X', 'X', 'O', 'X'},
{'X', 'X', 'X', 'O', 'X', 'X'},
{'O', 'X', 'X', 'X', 'X', 'X'},
{'X', 'X', 'X', 'O', 'X', 'O'},
{'O', 'O', 'X', 'O', 'O', 'O'},
};
fill(grid);
for (char[] row : grid) {
for (char c : row) {
System.out.print(c + " ");
}
System.out.println();
}
}
}
//Driver Code Ends
# A recursive function to replace previous value at '(x, y)'
# and all surrounding values of (x, y) with new value
def fillUtil(grid, x, y, prevV, newV):
m = len(grid)
n = len(grid[0])
# Base cases
if x < 0 or x >= m or y < 0 or y >= n:
return
if grid[x][y] != prevV:
return
# Replace current cell
grid[x][y] = newV
# Recur for 4 directions
fillUtil(grid, x+1, y, prevV, newV)
fillUtil(grid, x-1, y, prevV, newV)
fillUtil(grid, x, y+1, prevV, newV)
fillUtil(grid, x, y-1, prevV, newV)
def fill(grid):
m = len(grid)
n = len(grid[0])
# Replace all 'O' with '-'
for i in range(m):
for j in range(n):
if grid[i][j] == 'O':
grid[i][j] = '-'
# Flood fill for '-' on edges
for i in range(m):
if grid[i][0] == '-':
fillUtil(grid, i, 0, '-', 'O')
if grid[i][n - 1] == '-':
fillUtil(grid, i, n - 1, '-', 'O')
for j in range(n):
if grid[0][j] == '-':
fillUtil(grid, 0, j, '-', 'O')
if grid[m - 1][j] == '-':
fillUtil(grid, m - 1, j, '-', 'O')
# Replace remaining '-' with 'X'
for i in range(m):
for j in range(n):
if grid[i][j] == '-':
grid[i][j] = 'X'
#Driver Code Starts
if __name__ == "__main__":
grid = [
['X', 'O', 'X', 'O', 'X', 'X'],
['X', 'O', 'X', 'X', 'O', 'X'],
['X', 'X', 'X', 'O', 'X', 'X'],
['O', 'X', 'X', 'X', 'X', 'X'],
['X', 'X', 'X', 'O', 'X', 'O'],
['O', 'O', 'X', 'O', 'O', 'O'],
]
fill(grid)
for row in grid:
print(" ".join(row))
#Driver Code Ends
//Driver Code Starts
using System;
class GFG
{
//Driver Code Ends
// A recursive function to replace previous value at '(x, y)'
// and all surrounding values of (x, y) with new value
static void fillUtil(char[,] grid, int x, int y, char prevV, char newV)
{
int m = grid.GetLength(0);
int n = grid.GetLength(1);
// Base cases
if (x < 0 || x >= m || y < 0 || y >= n)
return;
if (grid[x, y] != prevV)
return;
// Replace current cell
grid[x, y] = newV;
// Recur for 4 directions
fillUtil(grid, x + 1, y, prevV, newV);
fillUtil(grid, x - 1, y, prevV, newV);
fillUtil(grid, x, y + 1, prevV, newV);
fillUtil(grid, x, y - 1, prevV, newV);
}
static void fill(char[,] grid)
{
int m = grid.GetLength(0);
int n = grid.GetLength(1);
// Replace all 'O' with '-'
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (grid[i, j] == 'O')
{
grid[i, j] = '-';
}
}
}
// Flood fill for '-' on edges
for (int i = 0; i < m; i++)
{
if (grid[i, 0] == '-') fillUtil(grid, i, 0, '-', 'O');
if (grid[i, n - 1] == '-') fillUtil(grid, i, n - 1, '-', 'O');
}
for (int j = 0; j < n; j++)
{
if (grid[0, j] == '-') fillUtil(grid, 0, j, '-', 'O');
if (grid[m - 1, j] == '-') fillUtil(grid, m - 1, j, '-', 'O');
}
// Replace remaining '-' with 'X'
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (grid[i, j] == '-')
{
grid[i, j] = 'X';
}
}
}
}
//Driver Code Starts
static void Main()
{
char[,] grid = {
{'X', 'O', 'X', 'O', 'X', 'X'},
{'X', 'O', 'X', 'X', 'O', 'X'},
{'X', 'X', 'X', 'O', 'X', 'X'},
{'O', 'X', 'X', 'X', 'X', 'X'},
{'X', 'X', 'X', 'O', 'X', 'O'},
{'O', 'O', 'X', 'O', 'O', 'O'},
};
fill(grid);
int m = grid.GetLength(0);
int n = grid.GetLength(1);
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(grid[i, j] + " ");
}
Console.WriteLine();
}
}
}
//Driver Code Ends
// A recursive function to replace previous value at '(x, y)'
// and all surrounding values of (x, y) with new value
function fillUtil(grid, x, y, prevV, newV) {
let m = grid.length;
let n = grid[0].length;
// Base cases
if (x < 0 || x >= m || y < 0 || y >= n) return;
if (grid[x][y] !== prevV) return;
// Replace current cell
grid[x][y] = newV;
// Recur for 4 directions
fillUtil(grid, x + 1, y, prevV, newV);
fillUtil(grid, x - 1, y, prevV, newV);
fillUtil(grid, x, y + 1, prevV, newV);
fillUtil(grid, x, y - 1, prevV, newV);
}
function fill(grid) {
let m = grid.length;
let n = grid[0].length;
// Replace all 'O' with '-'
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === 'O') {
grid[i][j] = '-';
}
}
}
// Flood fill for '-' on edges
for (let i = 0; i < m; i++) {
if (grid[i][0] === '-') fillUtil(grid, i, 0, '-', 'O');
if (grid[i][n - 1] === '-') fillUtil(grid, i, n - 1, '-', 'O');
}
for (let j = 0; j < n; j++) {
if (grid[0][j] === '-') fillUtil(grid, 0, j, '-', 'O');
if (grid[m - 1][j] === '-') fillUtil(grid, m - 1, j, '-', 'O');
}
// Replace remaining '-' with 'X'
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === '-') {
grid[i][j] = 'X';
}
}
}
}
//Driver Code Starts
// Driver Code
let grid = [
['X', 'O', 'X', 'O', 'X', 'X'],
['X', 'O', 'X', 'X', 'O', 'X'],
['X', 'X', 'X', 'O', 'X', 'X'],
['O', 'X', 'X', 'X', 'X', 'X'],
['X', 'X', 'X', 'O', 'X', 'O'],
['O', 'O', 'X', 'O', 'O', 'O']
];
fill(grid);
for (let row of grid) {
console.log(row.join(" "));
}
//Driver Code Ends
Output
X O X O X X X O X X X X X X X X X X O X X X X X X X X O X O O O X O O O
Time Complexity: O(m x n), where n is the number of rows and m is the number of columns.
Auxiliary Space: O(m x n), as implicit stack is used due to recursive call