Given a binary matrix containing only 0s and 1s. The task is to check whether there exists a rectangle or square submatrix of size at least 2 × 2 such that all four corners of that submatrix are 1.
This means we must find four positions in the matrix (top-left, top-right, bottom-left, and bottom-right, that are all 1, and they must form the corners of a valid rectangle).
Examples:
Input: mat[][] = [[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]]
Output : true
Explanation : There exists the below submatrix
1 0 1
0 1 0
1 0 1Input: mat[][] = [[1, 1, 1, 1],
[1, 0, 0, 1],
[1, 0, 0, 1],
[1, 1, 1, 1]]
Output : false
Explanation : There exists the below submatrix:
1 1 1 1
1 0 0 1
1 0 0 1
1 1 1 1Input: mat[][] = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 1]]
Output : false
Explanation: There is no rectangle with all corners as 1.
Table of Content
[Naive Approach] Check Every Submatrix - O((n^2)*(m^2)) Time and O(1) Space
The idea is to check all possible submatrices of size at least 2 × 2 by iterating through every pair of rows and every pair of columns. For each such combination (quadruple), we verify if the four corners of the submatrix are all 1s. If such a rectangle is found, we return true immediately. This approach ensures that we don't miss any valid configuration.
// C++ program to check if there exists a submatrix
// with all 1s at the corners using Naive Approach
#include <bits/stdc++.h>
using namespace std;
// Function to check for a rectangle with corners as 1
bool ValidCorner(vector<vector<int>> &mat) {
int rows = mat.size();
int cols = mat[0].size();
// Iterate over all pairs of rows
for (int top = 0; top < rows - 1; top++) {
for (int bottom = top + 1; bottom < rows; bottom++) {
// Iterate over all pairs of columns
for (int left = 0; left < cols - 1; left++) {
for (int right = left + 1; right < cols; right++) {
// Check all four corners of the submatrix
if (mat[top][left] == 1 && mat[top][right] == 1 &&
mat[bottom][left] == 1 && mat[bottom][right] == 1) {
return true;
}
}
}
}
}
// No such rectangle found
return false;
}
// Driver code
int main() {
vector<vector<int>> mat = {
{1, 0, 0, 1, 0},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 0},
{1, 0, 1, 0, 1}
};
if (ValidCorner(mat)) {
cout << "true";
}
else {
cout << "false";
}
return 0;
}
// Java program to check if there exists a submatrix
// with all 1s at the corners using Naive Approach
class GfG {
// Function to check for a rectangle with corners as 1
static boolean ValidCorner(int[][] mat) {
int rows = mat.length;
int cols = mat[0].length;
// Iterate over all pairs of rows
for (int top = 0; top < rows - 1; top++) {
for (int bottom = top + 1; bottom < rows; bottom++) {
// Iterate over all pairs of columns
for (int left = 0; left < cols - 1; left++) {
for (int right = left + 1; right < cols; right++) {
// Check all four corners of the submatrix
if (mat[top][left] == 1 && mat[top][right] == 1 &&
mat[bottom][left] == 1 && mat[bottom][right] == 1) {
return true;
}
}
}
}
}
// No such rectangle found
return false;
}
public static void main(String[] args) {
int[][] mat = {
{1, 0, 0, 1, 0},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 0},
{1, 0, 1, 0, 1}
};
System.out.print(ValidCorner(mat));
}
}
# Python program to check if there exists a submatrix
# with all 1s at the corners using Naive Approach
# Function to check for a rectangle with corners as 1
def ValidCorner(mat):
rows = len(mat)
cols = len(mat[0])
# Iterate over all pairs of rows
for top in range(rows - 1):
for bottom in range(top + 1, rows):
# Iterate over all pairs of columns
for left in range(cols - 1):
for right in range(left + 1, cols):
# Check all four corners of the submatrix
if (mat[top][left] == 1 and mat[top][right] == 1 and
mat[bottom][left] == 1 and mat[bottom][right] == 1):
return True
# No such rectangle found
return False
if __name__ == '__main__':
mat = [
[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]
]
if ValidCorner(mat):
print("true")
else:
print("false")
// C# program to check if there exists a submatrix
// with all 1s at the corners using Naive Approach
using System;
class GfG {
// Function to check for a rectangle with corners as 1
static bool ValidCorner(int[][] mat) {
int rows = mat.Length;
int cols = mat[0].Length;
// Iterate over all pairs of rows
for (int top = 0; top < rows - 1; top++) {
for (int bottom = top + 1; bottom < rows; bottom++) {
// Iterate over all pairs of columns
for (int left = 0; left < cols - 1; left++) {
for (int right = left + 1; right < cols; right++) {
// Check all four corners of the submatrix
if (mat[top][left] == 1 && mat[top][right] == 1 &&
mat[bottom][left] == 1 && mat[bottom][right] == 1) {
return true;
}
}
}
}
}
// No such rectangle found
return false;
}
static void Main() {
int[][] mat = new int[][] {
new int[] {1, 0, 0, 1, 0},
new int[] {0, 0, 1, 0, 1},
new int[] {0, 0, 0, 1, 0},
new int[] {1, 0, 1, 0, 1}
};
if (ValidCorner(mat)) {
Console.Write("true");
}
else {
Console.Write("false");
}
}
}
// JavaScript program to check if there exists a submatrix
// with all 1s at the corners using Naive Approach
// Function to check for a rectangle with corners as 1
function ValidCorner(mat) {
let rows = mat.length;
let cols = mat[0].length;
// Iterate over all pairs of rows
for (let top = 0; top < rows - 1; top++) {
for (let bottom = top + 1; bottom < rows; bottom++) {
// Iterate over all pairs of columns
for (let left = 0; left < cols - 1; left++) {
for (let right = left + 1; right < cols; right++) {
// Check all four corners of the submatrix
if (mat[top][left] === 1 && mat[top][right] === 1 &&
mat[bottom][left] === 1 && mat[bottom][right] === 1) {
return true;
}
}
}
}
}
// No such rectangle found
return false;
}
let mat = [
[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]
];
console.log(ValidCorner(mat))
Output
true
[Better Approach] Using Hashing - O(n*(m^2)) Time and O(n*m) Space
The idea is to use hashing to avoid checking every submatrix explicitly. We need to track column pairs with 1s in each row using a set. If the same pair of columns has 1s in more than one row, then a submatrix with all 1s at corners must exist. This works because repeating column pairs across rows form the top and bottom of a valid submatrix.
// C++ program to check if there exists a submatrix
// with all 1s at the corners using Simple Hashing
#include <bits/stdc++.h>
using namespace std;
// Function to check for a rectangle with corners as 1
bool ValidCorner(vector<vector<int>> &mat) {
int rows = mat.size();
int cols = mat[0].size();
// Hash set to store pairs of columns having 1 in a row
unordered_set<string> seen;
// Iterate through each row
for (int i = 0; i < rows; i++) {
// Check all column pairs where cell is 1
for (int col1 = 0; col1 < cols - 1; col1++) {
if (mat[i][col1] == 0) continue;
for (int col2 = col1 + 1; col2 < cols; col2++) {
if (mat[i][col2] == 0) continue;
// Form a unique key from column pair
string key = to_string(col1) + "," + to_string(col2);
// If this pair seen before → rectangle exists
if (seen.find(key) != seen.end()) {
return true;
}
// Otherwise store it
seen.insert(key);
}
}
}
// No rectangle found
return false;
}
// Driver code
int main() {
vector<vector<int>> mat = {
{1, 0, 0, 1, 0},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 0},
{1, 0, 1, 0, 1}
};
if (ValidCorner(mat)) {
cout << "true";
}
else {
cout << "false";
}
return 0;
}
// Java program to check if there exists a submatrix
// with all 1s at the corners using Simple Hashing
import java.util.*;
class GfG {
// Function to check for a rectangle with corners as 1
static boolean ValidCorner(int[][] mat) {
int rows = mat.length;
int cols = mat[0].length;
// Hash set to store pairs of columns having 1 in a row
HashSet<String> seen = new HashSet<>();
// Iterate through each row
for (int i = 0; i < rows; i++) {
// Check all column pairs where cell is 1
for (int col1 = 0; col1 < cols - 1; col1++) {
if (mat[i][col1] == 0) continue;
for (int col2 = col1 + 1; col2 < cols; col2++) {
if (mat[i][col2] == 0) continue;
// Form a unique key from column pair
String key = col1 + "," + col2;
// If this pair seen before → rectangle exists
if (seen.contains(key)) {
return true;
}
// Otherwise store it
seen.add(key);
}
}
}
// No rectangle found
return false;
}
// Driver code
public static void main(String[] args) {
int[][] mat = {
{1, 0, 0, 1, 0},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 0},
{1, 0, 1, 0, 1}
};
System.out.println(ValidCorner(mat));
}
}
# Python program to check if there exists a submatrix
# with all 1s at the corners using Simple Hashing
def ValidCorner(mat):
rows = len(mat)
cols = len(mat[0])
# Hash set to store pairs of columns having 1 in a row
seen = set()
# Iterate through each row
for i in range(rows):
# Check all column pairs where cell is 1
for col1 in range(cols - 1):
if mat[i][col1] == 0:
continue
for col2 in range(col1 + 1, cols):
if mat[i][col2] == 0:
continue
# Form a unique key from column pair
key = str(col1) + "," + str(col2)
# If this pair seen before → rectangle exists
if key in seen:
return True
# Otherwise store it
seen.add(key)
# No rectangle found
return False
# Driver code
if __name__ == "__main__":
mat = [
[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]
]
if ValidCorner(mat):
print("true")
else:
print("false")
// C# program to check if there exists a submatrix
// with all 1s at the corners using Simple Hashing
using System;
using System.Collections.Generic;
class GfG {
// Function to check for a rectangle with corners as 1
static bool ValidCorner(int[][] mat) {
int rows = mat.Length;
int cols = mat[0].Length;
// Hash set to store pairs of columns having 1 in a row
HashSet<string> seen = new HashSet<string>();
// Iterate through each row
for (int i = 0; i < rows; i++) {
// Check all column pairs where cell is 1
for (int col1 = 0; col1 < cols - 1; col1++) {
if (mat[i][col1] == 0) continue;
for (int col2 = col1 + 1; col2 < cols; col2++) {
if (mat[i][col2] == 0) continue;
// Form a unique key from column pair
string key = col1 + "," + col2;
// If this pair seen before → rectangle exists
if (seen.Contains(key)) {
return true;
}
// Otherwise store it
seen.Add(key);
}
}
}
// No rectangle found
return false;
}
// Driver code
public static void Main() {
int[][] mat = {
new int[] {1, 0, 0, 1, 0},
new int[] {0, 0, 1, 0, 1},
new int[] {0, 0, 0, 1, 0},
new int[] {1, 0, 1, 0, 1}
};
if (ValidCorner(mat)) {
Console.WriteLine("true");
}
else {
Console.WriteLine("false");
}
}
}
// JavaScript program to check if there exists a submatrix
// with all 1s at the corners using Simple Hashing
function ValidCorner(mat) {
let rows = mat.length;
let cols = mat[0].length;
// Hash set to store pairs of columns having 1 in a row
let seen = new Set();
// Iterate through each row
for (let i = 0; i < rows; i++) {
// Check all column pairs where cell is 1
for (let col1 = 0; col1 < cols - 1; col1++) {
if (mat[i][col1] === 0) continue;
for (let col2 = col1 + 1; col2 < cols; col2++) {
if (mat[i][col2] === 0) continue;
// Form a unique key from column pair
let key = col1 + "," + col2;
// If this pair seen before → rectangle exists
if (seen.has(key)) {
return true;
}
// Otherwise store it
seen.add(key);
}
}
}
// No rectangle found
return false;
}
// Driver code
let mat = [
[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]
];
console.log(ValidCorner(mat));
Output
true
[Expected Approach] Using Sparse-Dense Row Strategy
Instead of checking every possible rectangle directly, it optimizes the search by analyzing rows with 1s and checking for repeating column pairs. Rows are categorized as dense or sparse to reduce time complexity by using different strategies for each.
We can see that two rows share at least two common columns with 1s, then those column indices form the vertical sides of a rectangle, and the two rows form the horizontal sides. So, we only need to find such row pairs with common 1-columns at the same indices.
So, to Solve this, First processes each row to record the columns that have 1s. For sparse rows (having fewer 1s), it stores every unique pair of column indices and checks if the same pair appeared before — indicating a rectangle with a previous row. For dense rows (many 1s), it compares against all earlier rows to count how many 1-columns they share, and returns true if at least two are common.
#include <vector>
#include <unordered_set>
#include <cmath>
#include<iostream>
using namespace std;
bool ValidCorner(vector<vector<int> >& mat){
int n = mat.size();
int m = mat[0].size();
vector<vector<int>> rows(n);
int totalOnes = 0;
// collect columns with 1s
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (mat[i][j]) {
rows[i].push_back(j);
totalOnes++;
}
}
}
int threshold = sqrt(totalOnes);
// pairSeen[c1][c2] = whether any previous row had both c1 and c2
static bool pairSeen[205][205];
memset(pairSeen, false, sizeof(pairSeen));
// For dense rows: mark column presence
vector<bool> present(m);
for (int r = 0; r < n; r++) {
// Dense row
if ((int)rows[r].size() >= threshold) {
fill(present.begin(), present.end(), false);
for (int c : rows[r]) present[c] = true;
// Check all column pairs directly
for (int i = 0; i < m; i++) {
if (!present[i]) continue;
for (int j = i + 1; j < m; j++) {
if (present[j]) {
if (pairSeen[i][j])
return true; // rectangle found
pairSeen[i][j] = true;
}
}
}
}
// Sparse row
else {
for (int i = 0; i < rows[r].size(); i++) {
for (int j = i + 1; j < rows[r].size(); j++) {
int c1 = rows[r][i];
int c2 = rows[r][j];
if (pairSeen[c1][c2])
return true; // rectangle found
pairSeen[c1][c2] = true;
}
}
}
}
return false;
}
int main() {
vector<vector<int>> mat = {
{1, 0, 0, 1, 0},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 0},
{1, 0, 1, 0, 1}
};
if (ValidCorner(mat)) {
cout << "true";
}
else {
cout << "false";
}
return 0;
}
import java.util.*;
class GfG {
static boolean ValidCorner(int[][] mat) {
int n = mat.length;
int m = mat[0].length;
List<List<Integer>> rows = new ArrayList<>();
int totalOnes = 0;
// collect columns with 1s
for (int i = 0; i < n; i++) {
List<Integer> cols = new ArrayList<>();
for (int j = 0; j < m; j++) {
if (mat[i][j] == 1) {
cols.add(j);
totalOnes++;
}
}
rows.add(cols);
}
int threshold = (int) Math.sqrt(totalOnes);
// pairSeen[c1][c2] = whether any previous row had both c1 and c2
boolean[][] pairSeen = new boolean[205][205];
// For dense rows: mark column presence
boolean[] present = new boolean[m];
for (int r = 0; r < n; r++) {
// Dense row
if (rows.get(r).size() >= threshold) {
Arrays.fill(present, false);
for (int c : rows.get(r)) {
present[c] = true;
}
// Check all column pairs directly
for (int i = 0; i < m; i++) {
if (!present[i]) continue;
for (int j = i + 1; j < m; j++) {
if (present[j]) {
if (pairSeen[i][j])
return true; // rectangle found
pairSeen[i][j] = true;
}
}
}
}
// Sparse row
else {
List<Integer> row = rows.get(r);
for (int i = 0; i < row.size(); i++) {
for (int j = i + 1; j < row.size(); j++) {
int c1 = row.get(i);
int c2 = row.get(j);
if (pairSeen[c1][c2])
return true; // rectangle found
pairSeen[c1][c2] = true;
}
}
}
}
return false;
}
public static void main(String[] args) {
int[][] mat = {
{1, 0, 0, 1, 0},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 0},
{1, 0, 1, 0, 1}
};
System.out.println(ValidCorner(mat) ? "true" : "false");
}
}
import math
def ValidCorner(mat):
n = len(mat)
m = len(mat[0])
rows = []
totalOnes = 0
# collect columns with 1s
for i in range(n):
cols = []
for j in range(m):
if mat[i][j] == 1:
cols.append(j)
totalOnes += 1
rows.append(cols)
threshold = int(math.sqrt(totalOnes))
# pairSeen[c1][c2] = whether any previous row had both c1 and c2
pairSeen = [[False] * 205 for _ in range(205)]
# For dense rows: mark column presence
present = [False] * m
for r in range(n):
# Dense row
if len(rows[r]) >= threshold:
for i in range(m):
present[i] = False
for c in rows[r]:
present[c] = True
# Check all column pairs directly
for i in range(m):
if not present[i]:
continue
for j in range(i + 1, m):
if present[j]:
if pairSeen[i][j]:
return True # rectangle found
pairSeen[i][j] = True
# Sparse row
else:
row = rows[r]
for i in range(len(row)):
for j in range(i + 1, len(row)):
c1 = row[i]
c2 = row[j]
if pairSeen[c1][c2]:
return True # rectangle found
pairSeen[c1][c2] = True
return False
# Custom Input
if __name__ == "__main__":
mat = [
[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]
]
print("true" if ValidCorner(mat) else "false")
using System;
using System.Collections.Generic;
class GfG {
static bool ValidCorner(int[,] mat) {
int n = mat.GetLength(0);
int m = mat.GetLength(1);
List<List<int>> rows = new List<List<int>>();
int totalOnes = 0;
// collect columns with 1s
for (int i = 0; i < n; i++) {
List<int> cols = new List<int>();
for (int j = 0; j < m; j++) {
if (mat[i, j] == 1) {
cols.Add(j);
totalOnes++;
}
}
rows.Add(cols);
}
int threshold = (int)Math.Sqrt(totalOnes);
// pairSeen[c1][c2] = whether any previous row had both c1 and c2
bool[,] pairSeen = new bool[205, 205];
// For dense rows: mark column presence
bool[] present = new bool[m];
for (int r = 0; r < n; r++) {
// Dense row
if (rows[r].Count >= threshold) {
Array.Clear(present, 0, m);
foreach (int c in rows[r]) {
present[c] = true;
}
// Check all column pairs directly
for (int i = 0; i < m; i++) {
if (!present[i]) continue;
for (int j = i + 1; j < m; j++) {
if (present[j]) {
if (pairSeen[i, j])
return true; // rectangle found
pairSeen[i, j] = true;
}
}
}
}
// Sparse row
else {
var row = rows[r];
for (int i = 0; i < row.Count; i++) {
for (int j = i + 1; j < row.Count; j++) {
int c1 = row[i];
int c2 = row[j];
if (pairSeen[c1, c2])
return true; // rectangle found
pairSeen[c1, c2] = true;
}
}
}
}
return false;
}
static void Main() {
int[,] mat = {
{1, 0, 0, 1, 0},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 0},
{1, 0, 1, 0, 1}
};
Console.WriteLine(ValidCorner(mat) ? "true" : "false");
}
}
function ValidCorner(mat) {
let n = mat.length;
let m = mat[0].length;
let rows = [];
let totalOnes = 0;
// collect columns with 1s
for (let i = 0; i < n; i++) {
let cols = [];
for (let j = 0; j < m; j++) {
if (mat[i][j] === 1) {
cols.push(j);
totalOnes++;
}
}
rows.push(cols);
}
let threshold = Math.floor(Math.sqrt(totalOnes));
// pairSeen[c1][c2] = whether any previous row had both c1 and c2
let pairSeen = Array.from({ length: 205 }, () => Array(205).fill(false));
// For dense rows: mark column presence
let present = Array(m).fill(false);
for (let r = 0; r < n; r++) {
// Dense row
if (rows[r].length >= threshold) {
present.fill(false);
for (let c of rows[r]) {
present[c] = true;
}
// Check all column pairs directly
for (let i = 0; i < m; i++) {
if (!present[i]) continue;
for (let j = i + 1; j < m; j++) {
if (present[j]) {
if (pairSeen[i][j])
return true; // rectangle found
pairSeen[i][j] = true;
}
}
}
}
// Sparse row
else {
let row = rows[r];
for (let i = 0; i < row.length; i++) {
for (let j = i + 1; j < row.length; j++) {
let c1 = row[i];
let c2 = row[j];
if (pairSeen[c1][c2])
return true; // rectangle found
pairSeen[c1][c2] = true;
}
}
}
}
return false;
}
// Driver Code
let mat = [
[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]
];
console.log(ValidCorner(mat) ? "true" : "false");
Output
true
Time complexity: O(r * c + N√N + √N * c²), where N is the total number of 1s in the matrix and r and c are the number of rows and columns respectively. In the worst case (N ≈ r * c), this becomes O(r * c * √(r * c))
Auxiliary space: O(N + c²), for storing column indices of all 1’s in the matrix and for maintaining the column-pair tracking structure.