In the maximal square problem we have given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s, and return its area.
Table of Contents
Example
Input:
1 0 1 0 0
0 0 1 1 1
1 1 1 1 1
0 0 0 1 0
Output:
4
Brute Force Approach
The brute force way to solve this problem is to iterate over all the possible square sub-matrix and choose the maximum from them.
C++ program for Maximal square
#include <bits/stdc++.h> using namespace std; int maximalSquare(vector<vector<char>> &matrix) { int answer = 0; int n = matrix.size(); if (n == 0) { return 0; } int m = matrix[0].size(); if (m == 0) { return 0; } for (int sidelength = 1; sidelength <= min(n, m); sidelength++) // sidelength denotes the side length of the sub-matrix { // i,j are the top left index of the current sub-matrix for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if ((i + sidelength > n) or (j + sidelength > m)) //check if the current sub-matrix is not out of bounds { continue; } bool zero = false; // check if this sub matrix contain any zero or not for (int x = i; x < i + sidelength; x++) { for (int y = j; y < j + sidelength; y++) { if (matrix[x][y] == '0') { zero = true; } } } if (zero == false) // if this does not contain any zero than this is a valid sub matrix { answer = max(answer, sidelength * sidelength); } } } } return answer; } int main() { int n, m; cin >> n >> m; vector<vector<char>> matrix(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> matrix[i][j]; } } int answer = maximalSquare(matrix); cout << answer << endl; return 0; }
4 4 1 0 1 0 1 0 1 1 1 1 1 1 1 0 0 1
4
JAVA program for Maximal square
import java.util.*; public class Main { public static int maximalSquare(char[][] matrix) { int answer = 0; int n = matrix.length; if (n == 0) { return 0; } int m = matrix[0].length; if (m == 0) { return 0; } for (int sidelength = 1; sidelength <= Math.min(n, m); sidelength++) // sidelength denotes the side length of the sub-matrix { // i,j are the top left index of the current sub-matrix for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if ((i + sidelength > n) || (j + sidelength > m)) //check if the current sub-matrix is not out of bounds { continue; } boolean zero = false; // check if this sub matrix contain any zero or not for (int x = i; x < i + sidelength; x++) { for (int y = j; y < j + sidelength; y++) { if (matrix[x][y] == '0') { zero = true; } } } if (zero == false) // if this does not contain any zero than this is a valid sub matrix { answer = Math.max(answer, sidelength * sidelength); } } } } return answer; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt();; char[][] matrix = new char[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { matrix[i][j] = sc.next().charAt(0); } } int answer = maximalSquare(matrix); System.out.println(answer); } }
4 5 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0
9
Complexity Analysis
Time complexity
As we iterate over all the squares and there will be approx N^2 squares so the total time complexity is O(N^4).
Space complexity
As we have not used any extra space so the space complexity is O(1).
Dynamic Programming Approach
Explanation
Let say we have a dp array of size (n+1,m+1) where dp[i][j] represents the largest side length of a square of all ones whose top left corner is I,j.
So, if matrix[i][j] is one than we can say dp[i][j]=1+min(dp[i-1],dp[i][j-1],dp[i-1][j-1]) because the largest square of ones with top left corner I,j is just intersection of the largest squares of ones with top left corner (i-1,j),(I,j-1),(i-1,j-1).
Algorithm
- Initialize a dp array of size (n+1,m+1) with zeroes.
- Initialize a integer ans with zero.
- Iterate over all cells of the matrix.
- If matrix[i][j] is one than update dp[i][j]=1+ min(dp[i-1],dp[i][j-1],dp[i-1][j-1]).
- Update ans=max(ans,dp[i][j]).
- Return ans.
For example:
Matrix[][]={{‘1’, ‘0’, ‘1’, ‘0’, ‘0’},
{‘1’, ‘0’, ‘1’, ‘1’, ‘1’},
{ ‘1’, ‘1’, ‘1’, ‘1’, ‘1’},
{‘1’, ‘0’, ‘0’, ‘1’, ‘0’}}
For this matrix, the dp[][] array which look like this:
dp[i][j] denotes the side length of the maximum square of ones whose top left corner has the index (i, j).
C++ program for Maximal square
#include <bits/stdc++.h> using namespace std; int maximalSquare(vector<vector<char>> &matrix) { int n = matrix.size(); if (n == 0) { return 0; } int m = matrix[0].size(); if (m == 0) { return 0; } int ans = 0; vector<vector<int>> dp(n, vector<int>(m, 0)); for (int i = n - 1; i >= 0; i--) { if (matrix[i][m - 1] == '1') { dp[i][m - 1]++; ans = 1; } } for (int i = m - 1; i >= 0; i--) { if (matrix[n - 1][i] == '1') { dp[n - 1][i]++; ans = 1; } } for (int i = n - 2; i >= 0; i--) { for (int j = m - 2; j >= 0; j--) { if (matrix[i][j] == '1') { dp[i][j] = min(dp[i + 1][j + 1], min(dp[i + 1][j], dp[i][j + 1])) + 1; ans = max(ans, dp[i][j]); } } } return ans * ans; } int main() { int n, m; cin >> n >> m; vector<vector<char>> matrix(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> matrix[i][j]; } } int answer = maximalSquare(matrix); cout << answer << endl; return 0; }
4 2 1 0 1 1 1 1 1 0
4
JAVA program for Maximal square
import java.util.*; public class Main { public static int maximalSquare(char[][] matrix) { int n = matrix.length; if (n == 0) { return 0; } int m = matrix[0].length; if (m == 0) { return 0; } int ans = 0; int[][] dp = new int[n][m]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ dp[i][j]=0; } } for (int i = n - 1; i >= 0; i--) { if (matrix[i][m - 1] == '1') { dp[i][m - 1]++; ans = 1; } } for (int i = m - 1; i >= 0; i--) { if (matrix[n - 1][i] == '1') { dp[n - 1][i]++; ans = 1; } } for (int i = n - 2; i >= 0; i--) { for (int j = m - 2; j >= 0; j--) { if (matrix[i][j] == '1') { dp[i][j] = Math.min(dp[i + 1][j + 1], Math.min(dp[i + 1][j], dp[i][j + 1])) + 1; ans = Math.max(ans, dp[i][j]); } } } return ans * ans; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt();; char[][] matrix = new char[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { matrix[i][j] = sc.next().charAt(0); } } int answer = maximalSquare(matrix); System.out.println(answer); } }
4 5 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
16
Complexity Analysis
Time complexity
As we iterate over the matrix only once so the time complexity is O(N^2).
Space complexity
We took a dp array of size (n+1,m+1) so the space complexity is O(N^N).