# Check if a matrix contains a square submatrix with 0 as boundary element

Given an N*N binary matrix arr[][], the task is to check if the matrix contains a square of at least size 2 x 2 whose boundaries are made up of only 0s.

Examples:

Input:
arr[][] = {
{1, 1, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 1},
{0, 1, 1, 1, 0, 1},
{0, 0, 0, 1, 0, 1},
{0, 1, 1, 1, 0, 1},
{0, 0, 0, 0, 0, 1}
}
Output: True
Explanation:
Since, arr[][] contains square matrix with all 0’s at boundary, so answer is True.
{
{  ,  ,  ,  ,  , },
{0,   0,   0,   0,   0, },
{0,  ,  ,  ,   0, },
{0,  ,  ,  ,   0, },
{0,  ,  ,  ,  0, },
{0,   0,   0,   0,   0, }
}

Input:
arr[][] = {
{1, 1, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 1},
{0, 1, 1, 1, 0, 1},
{0, 0, 0, 1, 1, 1},
{0, 1, 1, 1, 0, 1},
{0, 0, 0, 0, 0, 1}
}
Output: False
Explanation: There is no square in the matrix whose borders are made up of only 0s.

Approach:

1. A square is defined by its topmost and bottommost rows and by its leftmost and rightmost columns.
2. Given a pair of rows and a pair of columns that form a valid square, you can easily determine if the relevant square is a square of zeroes with two for loops.
3. It is required to iterate over every valid square in the input matrix, arr[][].
4. We can start iterating from the outermost square and recursively go inwards in the matrix.
5. On moving inward, from (r1, c1) and (r2, c2) we have 5 options, which will generate square matrix:-
a) (r1 + 1, c1 + 1), (r2 – 1, c2 – 1)
b) (r1, c1 + 1), (r2 – 1, c2)
c) (r1 + 1, c1), (r2, c2 – 1)
d) (r1 + 1, c1 + 1), (r2, c2)
e) (r1, c1), (r2 – 1, c2 – 1)
6. Since, the problem has many overlapping sub-problem, so we need to use cache/memoization to avoid duplicate computations.

Below is the implementation of the above approach:

 `// C++ implementation of the above approach ` ` `  `#include ` `using` `namespace` `std; ` ` `  `bool` `hasSquareOfZeroes( ` `    ``vector >& matrix, ` `    ``int` `r1, ``int` `c1, ``int` `r2, ``int` `c2, ` `    ``unordered_map& cache); ` ` `  `bool` `isSquareOfZeroes( ` `    ``vector >& matrix, ` `    ``int` `r1, ``int` `c1, ` `    ``int` `r2, ``int` `c2); ` ` `  `// Function checks if square ` `// with all 0's in boundary ` `// exists in the matrix ` `bool` `squareOfZeroes( ` `    ``vector > matrix) ` `{ ` `    ``int` `lastIdx = matrix.size() - 1; ` `    ``unordered_map cache; ` `    ``return` `hasSquareOfZeroes( ` `        ``matrix, ` `        ``0, 0, ` `        ``lastIdx, ` `        ``lastIdx, ` `        ``cache); ` `} ` ` `  `// Function iterate inward in ` `// the matrix and checks the ` `// square obtained and memoize/cache ` `// the result to avoid duplicate computation ` ` `  `// r1 is the top row, ` `// c1 is the left col ` `// r2 is the bottom row, ` `// c2 is the right ` `bool` `hasSquareOfZeroes( ` `    ``vector >& matrix, ` `    ``int` `r1, ``int` `c1, ``int` `r2, ``int` `c2, ` `    ``unordered_map& cache) ` `{ ` `    ``if` `(r1 >= r2 || c1 >= c2) ` `        ``return` `false``; ` `    ``string key = to_string(r1) + ``'-'` `                 ``+ to_string(c1) + ``'-'` `                 ``+ to_string(r2) + ``'-'` `                 ``+ to_string(c2); ` ` `  `    ``if` `(cache.find(key) != cache.end()) ` `        ``return` `cache[key]; ` ` `  `    ``cache[key] ` `        ``= isSquareOfZeroes( ` `              ``matrix, r1, c1, r2, c2) ` `          ``|| hasSquareOfZeroes( ` `                 ``matrix, r1 + 1, c1 + 1, ` `                 ``r2 - 1, c2 - 1, cache) ` `          ``|| hasSquareOfZeroes( ` `                 ``matrix, r1, c1 + 1, ` `                 ``r2 - 1, c2, cache) ` `          ``|| hasSquareOfZeroes( ` `                 ``matrix, r1 + 1, c1, ` `                 ``r2, c2 - 1, cache) ` `          ``|| hasSquareOfZeroes( ` `                 ``matrix, r1 + 1, c1 + 1, ` `                 ``r2, c2, cache) ` `          ``|| hasSquareOfZeroes( ` `                 ``matrix, r1, c1, ` `                 ``r2 - 1, c2 - 1, cache); ` ` `  `    ``return` `cache[key]; ` `} ` ` `  `// Function checks if the ` `// boundary of the square ` `// consists of 0's ` `bool` `isSquareOfZeroes( ` `    ``vector >& matrix, ` `    ``int` `r1, ``int` `c1, ` `    ``int` `r2, ``int` `c2) ` `{ ` `    ``for` `(``int` `row = r1; row < r2 + 1; row++) { ` `        ``if` `(matrix[row][c1] != 0 ` `            ``|| matrix[row][c2] != 0) ` `            ``return` `false``; ` `    ``} ` `    ``for` `(``int` `col = c1; col < c2 + 1; col++) { ` `        ``if` `(matrix[r1][col] != 0 ` `            ``|| matrix[r2][col] != 0) ` `            ``return` `false``; ` `    ``} ` `    ``return` `true``; ` `} ` ` `  `// Driver Code ` `int` `main() ` `{ ` `    ``vector > matrix{ ` `        ``{ 1, 1, 1, 0, 1, 0 }, ` `        ``{ 0, 0, 0, 0, 0, 1 }, ` `        ``{ 0, 1, 1, 1, 0, 1 }, ` `        ``{ 0, 0, 0, 1, 0, 1 }, ` `        ``{ 0, 1, 1, 1, 0, 1 }, ` `        ``{ 0, 0, 0, 0, 0, 1 } ` `    ``}; ` `    ``int` `ans; ` `    ``ans = squareOfZeroes(matrix); ` ` `  `    ``if` `(ans == 1) { ` `        ``cout << ``"True"` `<< endl; ` `    ``} ` `    ``else` `{ ` `        ``cout << ``"False"` `<< endl; ` `    ``} ` `} `

Output:
```True
```

Time Complexity: O(N^4)
Space Complexity: O(N^3)

Efficient Approach: In order to optimize the above approach, we need to follow the below steps:

1. We need to precompute two values for every element in the matrix: the number of 0s to the right of each element (including the element itself) and the number of 0s below each element (including the element itself).
2. We can compute these values by iterating through the matrix starting at the bottom right corner and moving way up by traversing each row from right to left.
3. Once, we have computed the matrix, then we can check the boundary of square whether it is made up of all 0’s in constant time.
4. To check the boundary of the square, we just need to look at the number of 0s below any square’s two top corners and the number of 0s to the right of the same square’s two left corners.
1. Below is the implementation of the above approach:

 `// C++ implementation of the above approach ` ` `  `#include ` `using` `namespace` `std; ` ` `  `// Structure to store precomputed ` `// value corresponding to each ` `// element of the matrix ` `struct` `InfoMatrixItem { ` `    ``int` `numZeroesBelow; ` `    ``int` `numZeroesRight; ` `}; ` `bool` `isSquareOfZeroes( ` `    ``vector > ` `        ``infoMatrix, ` `    ``int` `r1, ``int` `c1, ` `    ``int` `r2, ``int` `c2); ` ` `  `vector > ` `preComputedNumOfZeroes( ` `    ``vector > matrix); ` ` `  `bool` `squareOfZeroes( ` `    ``vector > matrix) ` `{ ` `    ``vector > infoMatrix ` `        ``= preComputedNumOfZeroes(matrix); ` ` `  `    ``int` `n = matrix.size(); ` ` `  `    ``for` `(``int` `topRow = 0; ` `         ``topRow < n; ` `         ``topRow++) { ` ` `  `        ``for` `(``int` `leftCol = 0; ` `             ``leftCol < n; ` `             ``leftCol++) { ` ` `  `            ``int` `squareLength = 2; ` ` `  `            ``while` `(squareLength <= n - leftCol ` `                   ``&& squareLength <= n - topRow) { ` ` `  `                ``int` `bottomRow = topRow ` `                                ``+ squareLength - 1; ` `                ``int` `rightCol = leftCol ` `                               ``+ squareLength - 1; ` ` `  `                ``if` `(isSquareOfZeroes( ` `                        ``infoMatrix, topRow, ` `                        ``leftCol, bottomRow, ` `                        ``rightCol)) ` `                    ``return` `true``; ` ` `  `                ``squareLength++; ` `            ``} ` `        ``} ` `    ``} ` ` `  `    ``return` `false``; ` `} ` ` `  `// r1 is the top row, ` `// c1 is the left column ` `// r2 is the bottom row, ` `// c2 is the right column ` `bool` `isSquareOfZeroes( ` `    ``vector > ` `        ``infoMatrix, ` `    ``int` `r1, ``int` `c1, ` `    ``int` `r2, ``int` `c2) ` `{ ` ` `  `    ``int` `squareLength = c2 - c1 + 1; ` ` `  `    ``bool` `hasTopBorder ` `        ``= infoMatrix[r1][c1].numZeroesRight ` `          ``>= squareLength; ` `    ``bool` `hasLeftBorder ` `        ``= infoMatrix[r1][c1].numZeroesBelow ` `          ``>= squareLength; ` `    ``bool` `hasBottomBorder ` `        ``= infoMatrix[r2][c1].numZeroesRight ` `          ``>= squareLength; ` `    ``bool` `hasRightBorder ` `        ``= infoMatrix[r1][c2].numZeroesBelow ` `          ``>= squareLength; ` ` `  `    ``return` `hasTopBorder ` `           ``&& hasLeftBorder ` `           ``&& hasBottomBorder ` `           ``&& hasRightBorder; ` `} ` ` `  `vector > ` `preComputedNumOfZeroes( ` `    ``vector > matrix) ` `{ ` ` `  `    ``vector > infoMatrix; ` ` `  `    ``for` `(``int` `i = 0; i < matrix.size(); i++) { ` ` `  `        ``vector inner; ` ` `  `        ``for` `(``int` `j = 0; ` `             ``j < matrix[i].size(); ` `             ``j++) { ` ` `  `            ``int` `numZeroes = matrix[i][j] == 0 ` `                                ``? 1 ` `                                ``: 0; ` ` `  `            ``inner.push_back(InfoMatrixItem{ ` `                ``numZeroes, numZeroes }); ` `        ``} ` ` `  `        ``infoMatrix.push_back(inner); ` `    ``} ` ` `  `    ``int` `lastIdx = matrix.size() - 1; ` ` `  `    ``for` `(``int` `row = lastIdx; ` `         ``row >= 0; row--) { ` `        ``for` `(``int` `col = lastIdx; ` `             ``col >= 0; col--) { ` ` `  `            ``if` `(matrix[row][col] == 1) ` `                ``continue``; ` ` `  `            ``if` `(row < lastIdx) { ` `                ``infoMatrix[row][col] ` `                    ``.numZeroesBelow ` `                    ``+= infoMatrix[row + 1] ` `                                 ``[col] ` `                                     ``.numZeroesBelow; ` `            ``} ` ` `  `            ``if` `(col < lastIdx) { ` `                ``infoMatrix[row][col] ` `                    ``.numZeroesRight ` `                    ``+= infoMatrix[row] ` `                                 ``[col + 1] ` `                                     ``.numZeroesRight; ` `            ``} ` `        ``} ` `    ``} ` `    ``return` `infoMatrix; ` `} ` ` `  `// Driver Code ` `int` `main() ` `{ ` `    ``vector > matrix{ ` `        ``{ 1, 1, 1, 0, 1, 0 }, ` `        ``{ 0, 0, 0, 0, 0, 1 }, ` `        ``{ 0, 1, 1, 1, 0, 1 }, ` `        ``{ 0, 0, 0, 1, 0, 1 }, ` `        ``{ 0, 1, 1, 1, 0, 1 }, ` `        ``{ 0, 0, 0, 0, 0, 1 } ` `    ``}; ` `    ``int` `ans; ` `    ``ans = squareOfZeroes(matrix); ` `    ``if` `(ans == 1) { ` `        ``cout << ``"True"` `<< endl; ` `    ``} ` `    ``else` `{ ` `        ``cout << ``"False"` `<< endl; ` `    ``} ` `} `

Output:
```True
```

Time Complexity : O(N^3)
Space Complexity : O(N^2)

I am currently pursuing B Tech (Hons) in Computer Science I love technology and explore new things I want to become a very good programmer I love to travel and meet new peoples

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.