Largest Subsquare Surrounded by X

Last Updated : 19 Sep, 2026

Given a square matrix mat[][] of size n × n, where each cell contains either 'X' or 'O'. Find the size of the largest square submatrix whose boundary is completely surrounded by 'X'. The cells inside the submatrix can contain either 'X' or 'O'. Only the four sides of the submatrix must contain 'X'.

Return the side length of the largest such square submatrix.

Note: A square of size 1 is valid if its only cell is 'X'. If no such square submatrix exists, return 0.

Examples:

Input: mat[][] = [[X,X,X,O],[X,O,X,X],[X,X,X,O],[X,O,X,X]]

2056958655

Output: 3
Explanation: Here, the input represents following matrix of size 4 x 4. The square submatrix starting at (0,0) and ending at (2,2) is the largest submatrix surrounded by X. Therefore, size of that matrix would be 3.

20569586552

Input: mat[][] = [[X,X],[X,X]]

2056958656

Output: 2
Explanation: The largest square submatrix surrounded by X is the whole input matrix.

Try It Yourself
redirect icon

[Naive Approach] Try All Possible Submatrices - O(n4) Time and O(1) Space

The idea is to iterate over each cell in the mat[][] and consider it as the top-left corner of potential square submatrices.

For each starting cell, we’ expand the square's size and check if the borders of that square consist entirely of 'X'. If they do, update the maximum size found.

C++
#include <iostream>
#include <vector>
using namespace std;

int largestSubsquare(vector<vector<char>> &mat)
{
    int n = mat.size();
    int maxSize = 0;

    // Traverse each cell in the matrix
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            // For each cell (i, j), consider it as the
            // top-left corner of squares of increasing sizes
            for (int size = 1; size <= n - max(i, j); size++)
            {
                // Check if the square of 'size' with top-left
                // corner (i, j) has its borders as 'X'
                bool valid = true;

                // Check top and left side of the current square
                for (int k = 0; k < size; k++)
                {
                    if (mat[i][j + k] != 'X' || mat[i + k][j] != 'X')
                    {
                        valid = false;
                        break;
                    }
                }

                // Check bottom and right sides of
                // the current square
                for (int k = 0; k < size; k++)
                {
                    if (mat[i + size - 1][j + k] != 'X' || mat[i + k][j + size - 1] != 'X')
                    {
                        valid = false;
                        break;
                    }
                }

                // If the current square is valid,
                // update the maximum size found
                if (valid)
                {
                    maxSize = max(maxSize, size);
                }
            }
        }
    }

    return maxSize;
}

int main()
{
    vector<vector<char>> mat = { {'X', 'X', 'X', 'O'}, 
                                 {'X', 'O', 'X', 'X'}, 
                                 {'X', 'X', 'X', 'O'}, 
                                 {'X', 'O', 'X', 'X'}};
                                 
    cout << largestSubsquare(mat) << endl;
}
Java
import java.util.Arrays;

class GFG {
    static int largestSubsquare(char[][] mat)
    {
        int n = mat.length;
        int maxSize = 0;

        // Traverse each cell in the matrix
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {

                // For each cell (i, j), consider it as the
                // top-left corner of squares of increasing
                // sizes
                for (int size = 1;
                     size <= n - Math.max(i, j); size++) {

                    // Check if the square of 'size' with
                    // top-left corner (i, j) has its
                    // borders as 'X'
                    boolean valid = true;

                    // Check top and left side of the
                    // current square
                    for (int k = 0; k < size; k++) {
                        if (mat[i][j + k] != 'X'
                            || mat[i + k][j] != 'X') {
                            valid = false;
                            break;
                        }
                    }

                    // Check bottom and right sides of the
                    // current square
                    for (int k = 0; k < size; k++) {
                        if (mat[i + size - 1][j + k] != 'X'
                            || mat[i + k][j + size - 1]
                                   != 'X') {
                            valid = false;
                            break;
                        }
                    }

                    // If the current square is valid,
                    // update the maximum size found
                    if (valid) {
                        maxSize = Math.max(maxSize, size);
                    }
                }
            }
        }

        return maxSize;
    }

    public static void main(String[] args)
    {
        char[][] mat = { { 'X', 'X', 'X', 'O' },
                         { 'X', 'O', 'X', 'X' },
                         { 'X', 'X', 'X', 'O' },
                         { 'X', 'O', 'X', 'X' } };
        System.out.println(largestSubsquare(mat));
    }
}
Python
def largestSubsquare(mat):
    n = len(mat)
    maxSize = 0

    # Traverse each cell in the matrix
    for i in range(n):
        for j in range(n):

            # For each cell (i, j), consider it as the
            # top-left corner of squares of increasing sizes
            for size in range(1, n - max(i, j) + 1):

                # Check if the square of 'size' with top-left
                # corner (i, j) has its borders as 'X'
                valid = True

                # Check top and left side of the current square
                for k in range(size):
                    if mat[i][j + k] != 'X' or mat[i + k][j] != 'X':
                        valid = False
                        break

                # Check bottom and right sides of the current square
                for k in range(size):
                    if mat[i + size - 1][j + k] != 'X' or \
                            mat[i + k][j + size - 1] != 'X':
                        valid = False
                        break

                # If the current square is valid,
                # update the maximum size found
                if valid:
                    maxSize = max(maxSize, size)

    return maxSize

# Driver Code
if __name__ == "__main__":

    mat = [
        ['X', 'X', 'X', 'O'],
        ['X', 'O', 'X', 'X'],
        ['X', 'X', 'X', 'O'],
        ['X', 'O', 'X', 'X']
    ]
    print(largestSubsquare(mat))
C#
using System;

class GFG {
    static int largestSubsquare(char[][] mat)
    {
        int n = mat.Length;
        int maxSize = 0;

        // Traverse each cell in the matrix
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {

                // For each cell (i, j), consider it as the
                // top-left corner of squares of increasing
                // sizes
                for (int size = 1;
                     size <= n - Math.Max(i, j); size++) {

                    // Check if the square of 'size' with
                    // top-left corner (i, j) has its
                    // borders as 'X'
                    bool valid = true;

                    // Check top and left side of the
                    // current square
                    for (int k = 0; k < size; k++) {
                        if (mat[i][j + k] != 'X'
                            || mat[i + k][j] != 'X') {
                            valid = false;
                            break;
                        }
                    }

                    // Check bottom and right sides of the
                    // current square
                    for (int k = 0; k < size; k++) {
                        if (mat[i + size - 1][j + k] != 'X'
                            || mat[i + k][j + size - 1]
                                   != 'X') {
                            valid = false;
                            break;
                        }
                    }

                    // If the current square is valid,
                    // update the maximum size found
                    if (valid) {
                        maxSize = Math.Max(maxSize, size);
                    }
                }
            }
        }

        return maxSize;
    }

    static void Main()
    {
        char[][] mat
            = { new char[] { 'X', 'X', 'X', 'O' },
                new char[] { 'X', 'O', 'X', 'X' },
                new char[] { 'X', 'X', 'X', 'O' },
                new char[] { 'X', 'O', 'X', 'X' } };
        Console.WriteLine(largestSubsquare(mat));
    }
}
JavaScript
function largestSubsquare(mat)
{
    let n = mat.length;
    let maxSize = 0;

    // Traverse each cell in the matrix
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {

            // For each cell (i, j), consider it as the
            // top-left corner of squares of increasing
            // sizes
            for (let size = 1; size <= n - Math.max(i, j);
                 size++) {

                // Check if the square of 'size' with
                // top-left corner (i, j) has its borders as
                // 'X'
                let valid = true;

                // Check top and left side of the current
                // square
                for (let k = 0; k < size; k++) {
                    if (mat[i][j + k] !== "X"
                        || mat[i + k][j] !== "X") {
                        valid = false;
                        break;
                    }
                }

                // Check bottom and right sides of the
                // current square
                for (let k = 0; k < size; k++) {
                    if (mat[i + size - 1][j + k] !== "X"
                        || mat[i + k][j + size - 1]
                               !== "X") {
                        valid = false;
                        break;
                    }
                }

                // If the current square is valid,
                // update the maximum size found
                if (valid) {
                    maxSize = Math.max(maxSize, size);
                }
            }
        }
    }

    return maxSize;
}

// Driver Code
const mat = [
    [ "X", "X", "X", "O" ], [ "X", "O", "X", "X" ],
    [ "X", "X", "X", "O" ], [ "X", "O", "X", "X" ]
];
console.log(largestSubsquare(mat));

Output
3

[Expected Approach] Precomputing Right and Down X Counts - O(n3) Time and O(n2) Space

The idea is to precompute how many consecutive Xs are present to the right and downward from every cell. Then, consider each cell as the top-left corner of a possible square.

The right and down values give the maximum possible size based on the top and left boundaries. For each possible size, we only need to check whether the bottom and right boundaries also contain enough consecutive Xs.

Step by step approach:

  • Create right and down arrays to store consecutive Xs towards the right and downward from each cell.
  • Traverse the matrix from bottom-right to top-left and fill both arrays.
  • Treat each cell (i, j) as the top-left corner of a possible square.
  • Set maxSide = min(right[i][j], down[i][j]) as the maximum possible side.
  • Try smaller sides and check whether the bottom and right boundaries also contain enough Xs.
  • Update the answer when a valid square is found and return the largest size.

Illustration:

largest-cross-bordered-square
C++
#include <iostream>
#include <vector>
using namespace std;

int largestSubsquare(vector<vector<char>> &mat)
{
    int n = mat.size();

    // Matrices to store count of 'X' to the right
    // and bottom of cells.
    vector<vector<int>> right(n, vector<int>(n, 0));
    vector<vector<int>> down(n, vector<int>(n, 0));

    // Fill the right and down matrices
    for (int i = n - 1; i >= 0; i--)
    {
        for (int j = n - 1; j >= 0; j--)
        {
            if (mat[i][j] == 'X')
            {
                right[i][j] = (j == n - 1) ? 1 : right[i][j + 1] + 1;
                down[i][j] = (i == n - 1) ? 1 : down[i + 1][j] + 1;
            }
        }
    }

    int maxSize = 0;

    // Check each cell as the top-left corner of the square
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            // Calculate the maximum possible side
            // length for the square starting at (i, j)
            int maxSide = min(right[i][j], down[i][j]);

            // Iterate from the maximum side length down to 1
            for (int side = maxSide; side > 0; side--)
            {
                // Check if the square of length
                // 'side' has valid borders
                if (right[i + side - 1][j] >= side && down[i][j + side - 1] >= side)
                {
                    maxSize = max(maxSize, side);
                    break;
                }
            }
        }
    }

    return maxSize;
}

int main()
{
    vector<vector<char>> mat = {{'X', 'X', 'X', 'O'}, 
                                {'X', 'O', 'X', 'X'}, 
                                {'X', 'X', 'X', 'O'}, 
                                {'X', 'O', 'X', 'X'}};
                                
    cout << largestSubsquare(mat) << endl;
}
Java
class GFG {
    static int largestSubsquare(char[][] mat)
    {
        int n = mat.length;

        // Matrices to store count of 'X' to the right
        // and bottom of cells.
        int[][] right = new int[n][n];
        int[][] down = new int[n][n];

        // Fill the right and down matrices
        for (int i = n - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                if (mat[i][j] == 'X') {
                    right[i][j] = (j == n - 1)
                                      ? 1
                                      : right[i][j + 1] + 1;
                    down[i][j] = (i == n - 1)
                                     ? 1
                                     : down[i + 1][j] + 1;
                }
            }
        }

        int maxSize = 0;

        // Check each cell as the top-left corner of the
        // square
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {

                // Calculate the maximum possible side
                // length for the square starting at (i, j)
                int maxSide
                    = Math.min(right[i][j], down[i][j]);

                // Iterate from the maximum side length down
                // to 1
                for (int side = maxSide; side > 0; side--) {

                    // Check if the square of length
                    // 'side' has valid borders
                    if (right[i + side - 1][j] >= side
                        && down[i][j + side - 1] >= side) {
                        maxSize = Math.max(maxSize, side);
                        break;
                    }
                }
            }
        }

        return maxSize;
    }

    public static void main(String[] args)
    {
        char[][] mat = { { 'X', 'X', 'X', 'O' },
                         { 'X', 'O', 'X', 'X' },
                         { 'X', 'X', 'X', 'O' },
                         { 'X', 'O', 'X', 'X' } };
        System.out.println(largestSubsquare(mat));
    }
}
Python
def largestSubsquare(mat):
    n = len(mat)

    # Matrices to store count of 'X' to the right
    # and bottom of cells.
    right = [[0] * n for _ in range(n)]
    down = [[0] * n for _ in range(n)]

    # Fill the right and down matrices
    for i in range(n - 1, -1, -1):
        for j in range(n - 1, -1, -1):
            if mat[i][j] == 'X':
                right[i][j] = 1 if j == n - 1 else right[i][j + 1] + 1
                down[i][j] = 1 if i == n - 1 else down[i + 1][j] + 1

    maxSize = 0

    # Check each cell as the top-left
    # corner of the square
    for i in range(n):
        for j in range(n):

            # Calculate the maximum possible side
            # length for the square starting at (i, j)
            maxSide = min(right[i][j], down[i][j])

            # Iterate from the maximum side length down to 1
            for side in range(maxSide, 0, -1):

                # Check if the square of length
                # 'side' has valid borders
                if right[i + side - 1][j] >= side and \
                        down[i][j + side - 1] >= side:
                    maxSize = max(maxSize, side)
                    break

    return maxSize

# Driver Code
if __name__ == "__main__":
    mat = [
        ['X', 'X', 'X', 'O'],
        ['X', 'O', 'X', 'X'],
        ['X', 'X', 'X', 'O'],
        ['X', 'O', 'X', 'X']
    ]
    print(largestSubsquare(mat))
C#
using System;

class GFG {
    static int largestSubsquare(char[][] mat)
    {
        int n = mat.Length;

        // Matrices to store count of 'X' to the right
        // and bottom of cells.
        int[, ] right = new int[n, n];
        int[, ] down = new int[n, n];

        // Fill the right and down matrices
        for (int i = n - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                if (mat[i][j] == 'X') {
                    right[i, j] = (j == n - 1)
                                      ? 1
                                      : right[i, j + 1] + 1;
                    down[i, j] = (i == n - 1)
                                     ? 1
                                     : down[i + 1, j] + 1;
                }
            }
        }

        int maxSize = 0;

        // Check each cell as the top-left corner of the
        // square
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {

                // Calculate the maximum possible side
                // length for the square starting at (i, j)
                int maxSide
                    = Math.Min(right[i, j], down[i, j]);

                // Iterate from the maximum side length down
                // to 1
                for (int side = maxSide; side > 0; side--) {

                    // Check if the square of length
                    // 'side' has valid borders
                    if (right[i + side - 1, j] >= side
                        && down[i, j + side - 1] >= side) {
                        maxSize = Math.Max(maxSize, side);
                        break;
                    }
                }
            }
        }

        return maxSize;
    }

    static void Main()
    {
        char[][] mat
            = { new char[] { 'X', 'X', 'X', 'O' },
                new char[] { 'X', 'O', 'X', 'X' },
                new char[] { 'X', 'X', 'X', 'O' },
                new char[] { 'X', 'O', 'X', 'X' } };
        Console.WriteLine(largestSubsquare(mat));
    }
}
JavaScript
function largestSubsquare(mat)
{
    let n = mat.length;

    // Matrices to store count of 'X' to the right
    // and bottom of cells.
    let right
        = Array.from({length : n}, () => Array(n).fill(0));
    let down
        = Array.from({length : n}, () => Array(n).fill(0));

    // Fill the right and down matrices
    for (let i = n - 1; i >= 0; i--) {
        for (let j = n - 1; j >= 0; j--) {
            if (mat[i][j] === "X") {
                right[i][j] = (j === n - 1)
                                  ? 1
                                  : right[i][j + 1] + 1;
                down[i][j] = (i === n - 1)
                                 ? 1
                                 : down[i + 1][j] + 1;
            }
        }
    }

    let maxSize = 0;

    // Check each cell as the top-left corner of the square
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {

            // Calculate the maximum possible side
            // length for the square starting at (i, j)
            let maxSide = Math.min(right[i][j], down[i][j]);

            // Iterate from the maximum side length down to
            // 1
            for (let side = maxSide; side > 0; side--) {

                // Check if the square of length
                // 'side' has valid borders
                if (right[i + side - 1][j] >= side
                    && down[i][j + side - 1] >= side) {
                    maxSize = Math.max(maxSize, side);
                    break;
                }
            }
        }
    }

    return maxSize;
}

// Driver Code
const mat = [
    [ "X", "X", "X", "O" ], [ "X", "O", "X", "X" ],
    [ "X", "X", "X", "O" ], [ "X", "O", "X", "X" ]
];
console.log(largestSubsquare(mat));

Output
3
Comment