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.
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.
Input: mat[][] = [[X,X],[X,X]]
Output: 2 Explanation: The largest square submatrix surrounded by X is the whole input matrix.
[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>usingnamespacestd;intlargestSubsquare(vector<vector<char>>&mat){intn=mat.size();intmaxSize=0;// Traverse each cell in the matrixfor(inti=0;i<n;i++){for(intj=0;j<n;j++){// For each cell (i, j), consider it as the// top-left corner of squares of increasing sizesfor(intsize=1;size<=n-max(i,j);size++){// Check if the square of 'size' with top-left// corner (i, j) has its borders as 'X'boolvalid=true;// Check top and left side of the current squarefor(intk=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 squarefor(intk=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 foundif(valid){maxSize=max(maxSize,size);}}}}returnmaxSize;}intmain(){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
importjava.util.Arrays;classGFG{staticintlargestSubsquare(char[][]mat){intn=mat.length;intmaxSize=0;// Traverse each cell in the matrixfor(inti=0;i<n;i++){for(intj=0;j<n;j++){// For each cell (i, j), consider it as the// top-left corner of squares of increasing// sizesfor(intsize=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'booleanvalid=true;// Check top and left side of the// current squarefor(intk=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 squarefor(intk=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 foundif(valid){maxSize=Math.max(maxSize,size);}}}}returnmaxSize;}publicstaticvoidmain(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
deflargestSubsquare(mat):n=len(mat)maxSize=0# Traverse each cell in the matrixforiinrange(n):forjinrange(n):# For each cell (i, j), consider it as the# top-left corner of squares of increasing sizesforsizeinrange(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 squareforkinrange(size):ifmat[i][j+k]!='X'ormat[i+k][j]!='X':valid=Falsebreak# Check bottom and right sides of the current squareforkinrange(size):ifmat[i+size-1][j+k]!='X'or \
mat[i+k][j+size-1]!='X':valid=Falsebreak# If the current square is valid,# update the maximum size foundifvalid:maxSize=max(maxSize,size)returnmaxSize# Driver Codeif__name__=="__main__":mat=[['X','X','X','O'],['X','O','X','X'],['X','X','X','O'],['X','O','X','X']]print(largestSubsquare(mat))
C#
usingSystem;classGFG{staticintlargestSubsquare(char[][]mat){intn=mat.Length;intmaxSize=0;// Traverse each cell in the matrixfor(inti=0;i<n;i++){for(intj=0;j<n;j++){// For each cell (i, j), consider it as the// top-left corner of squares of increasing// sizesfor(intsize=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'boolvalid=true;// Check top and left side of the// current squarefor(intk=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 squarefor(intk=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 foundif(valid){maxSize=Math.Max(maxSize,size);}}}}returnmaxSize;}staticvoidMain(){char[][]mat={newchar[]{'X','X','X','O'},newchar[]{'X','O','X','X'},newchar[]{'X','X','X','O'},newchar[]{'X','O','X','X'}};Console.WriteLine(largestSubsquare(mat));}}
JavaScript
functionlargestSubsquare(mat){letn=mat.length;letmaxSize=0;// Traverse each cell in the matrixfor(leti=0;i<n;i++){for(letj=0;j<n;j++){// For each cell (i, j), consider it as the// top-left corner of squares of increasing// sizesfor(letsize=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'letvalid=true;// Check top and left side of the current// squarefor(letk=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 squarefor(letk=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 foundif(valid){maxSize=Math.max(maxSize,size);}}}}returnmaxSize;}// Driver Codeconstmat=[["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:
C++
#include<iostream>#include<vector>usingnamespacestd;intlargestSubsquare(vector<vector<char>>&mat){intn=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 matricesfor(inti=n-1;i>=0;i--){for(intj=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;}}}intmaxSize=0;// Check each cell as the top-left corner of the squarefor(inti=0;i<n;i++){for(intj=0;j<n;j++){// Calculate the maximum possible side// length for the square starting at (i, j)intmaxSide=min(right[i][j],down[i][j]);// Iterate from the maximum side length down to 1for(intside=maxSide;side>0;side--){// Check if the square of length// 'side' has valid bordersif(right[i+side-1][j]>=side&&down[i][j+side-1]>=side){maxSize=max(maxSize,side);break;}}}}returnmaxSize;}intmain(){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
classGFG{staticintlargestSubsquare(char[][]mat){intn=mat.length;// Matrices to store count of 'X' to the right// and bottom of cells.int[][]right=newint[n][n];int[][]down=newint[n][n];// Fill the right and down matricesfor(inti=n-1;i>=0;i--){for(intj=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;}}}intmaxSize=0;// Check each cell as the top-left corner of the// squarefor(inti=0;i<n;i++){for(intj=0;j<n;j++){// Calculate the maximum possible side// length for the square starting at (i, j)intmaxSide=Math.min(right[i][j],down[i][j]);// Iterate from the maximum side length down// to 1for(intside=maxSide;side>0;side--){// Check if the square of length// 'side' has valid bordersif(right[i+side-1][j]>=side&&down[i][j+side-1]>=side){maxSize=Math.max(maxSize,side);break;}}}}returnmaxSize;}publicstaticvoidmain(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
deflargestSubsquare(mat):n=len(mat)# Matrices to store count of 'X' to the right# and bottom of cells.right=[[0]*nfor_inrange(n)]down=[[0]*nfor_inrange(n)]# Fill the right and down matricesforiinrange(n-1,-1,-1):forjinrange(n-1,-1,-1):ifmat[i][j]=='X':right[i][j]=1ifj==n-1elseright[i][j+1]+1down[i][j]=1ifi==n-1elsedown[i+1][j]+1maxSize=0# Check each cell as the top-left# corner of the squareforiinrange(n):forjinrange(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 1forsideinrange(maxSide,0,-1):# Check if the square of length# 'side' has valid bordersifright[i+side-1][j]>=sideand \
down[i][j+side-1]>=side:maxSize=max(maxSize,side)breakreturnmaxSize# Driver Codeif__name__=="__main__":mat=[['X','X','X','O'],['X','O','X','X'],['X','X','X','O'],['X','O','X','X']]print(largestSubsquare(mat))
C#
usingSystem;classGFG{staticintlargestSubsquare(char[][]mat){intn=mat.Length;// Matrices to store count of 'X' to the right// and bottom of cells.int[,]right=newint[n,n];int[,]down=newint[n,n];// Fill the right and down matricesfor(inti=n-1;i>=0;i--){for(intj=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;}}}intmaxSize=0;// Check each cell as the top-left corner of the// squarefor(inti=0;i<n;i++){for(intj=0;j<n;j++){// Calculate the maximum possible side// length for the square starting at (i, j)intmaxSide=Math.Min(right[i,j],down[i,j]);// Iterate from the maximum side length down// to 1for(intside=maxSide;side>0;side--){// Check if the square of length// 'side' has valid bordersif(right[i+side-1,j]>=side&&down[i,j+side-1]>=side){maxSize=Math.Max(maxSize,side);break;}}}}returnmaxSize;}staticvoidMain(){char[][]mat={newchar[]{'X','X','X','O'},newchar[]{'X','O','X','X'},newchar[]{'X','X','X','O'},newchar[]{'X','O','X','X'}};Console.WriteLine(largestSubsquare(mat));}}
JavaScript
functionlargestSubsquare(mat){letn=mat.length;// Matrices to store count of 'X' to the right// and bottom of cells.letright=Array.from({length:n},()=>Array(n).fill(0));letdown=Array.from({length:n},()=>Array(n).fill(0));// Fill the right and down matricesfor(leti=n-1;i>=0;i--){for(letj=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;}}}letmaxSize=0;// Check each cell as the top-left corner of the squarefor(leti=0;i<n;i++){for(letj=0;j<n;j++){// Calculate the maximum possible side// length for the square starting at (i, j)letmaxSide=Math.min(right[i][j],down[i][j]);// Iterate from the maximum side length down to// 1for(letside=maxSide;side>0;side--){// Check if the square of length// 'side' has valid bordersif(right[i+side-1][j]>=side&&down[i][j+side-1]>=side){maxSize=Math.max(maxSize,side);break;}}}}returnmaxSize;}// Driver Codeconstmat=[["X","X","X","O"],["X","O","X","X"],["X","X","X","O"],["X","O","X","X"]];console.log(largestSubsquare(mat));