Submatrix with corners as 1
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){
vector<vector<short>> rows;
int N = 0;
// Preprocess: Store columns with 1s for each row
for (const auto& row : mat) {
vector<short> cols;
for (short c = 0; c < row.size(); ++c) {
if (row[c]) cols.push_back(c);
}
rows.push_back(cols);
N += cols.size();
}
int sqrtN = sqrt(N);
unordered_set<int> pairs;
for (int r = 0; r < rows.size(); ++r) {
if (rows[r].size() >= sqrtN) {
// Dense row: Check against all previous rows
unordered_set<short> cols(rows[r].begin(), rows[r].end());
for (int r2 = 0; r2 < r; ++r2) {
int common = 0;
for (short c : rows[r2]) {
if (cols.count(c)) common++;
if (common >= 2) return true; // Early exit
}
}
} else {
// Sparse row: Check column pairs
for (int i = 0; i < rows[r].size(); ++i) {
for (int j = i+1; j < rows[r].size(); ++j) {
int key = (rows[r][i] << 13) | rows[r][j];
if (pairs.count(key)) return true;
pairs.insert(key);
}
}
}
}
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) {
List<List<Short>> rows = new ArrayList<>();
int N = 0;
// Preprocess: Store columns with 1s for each row
for (int[] row : mat) {
List<Short> cols = new ArrayList<>();
for (short c = 0; c < row.length; ++c) {
if (row[c] == 1) cols.add(c);
}
rows.add(cols);
N += cols.size();
}
int sqrtN = (int)Math.sqrt(N);
Set<Integer> pairs = new HashSet<>();
for (int r = 0; r < rows.size(); ++r) {
if (rows.get(r).size() >= sqrtN) {
// Dense row: Check against all previous rows
Set<Short> cols = new HashSet<>(rows.get(r));
for (int r2 = 0; r2 < r; ++r2) {
int common = 0;
for (short c : rows.get(r2)) {
if (cols.contains(c)) {
common++;
// Early exit
if (common >= 2) return true;
}
}
}
} else {
// Sparse row: Check column pairs
List<Short> row = rows.get(r);
for (int i = 0; i < row.size(); ++i) {
for (int j = i + 1; j < row.size(); ++j) {
int key = (row.get(i) << 13) | row.get(j);
if (pairs.contains(key)) return true;
pairs.add(key);
}
}
}
}
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):
rows = []
N = 0
# Preprocess: Store columns with 1s for each row
for row in mat:
cols = []
for c in range(len(row)):
if row[c] == 1:
cols.append(c)
rows.append(cols)
N += len(cols)
sqrtN = int(math.sqrt(N))
pairs = set()
for r in range(len(rows)):
if len(rows[r]) >= sqrtN:
# Dense row: Check against all previous rows
cols = set(rows[r])
for r2 in range(r):
common = 0
for c in rows[r2]:
if c in cols:
common += 1
if common >= 2:
return True # Early exit
else:
# Sparse row: Check column pairs
row = rows[r]
for i in range(len(row)):
for j in range(i + 1, len(row)):
key = (row[i] << 13) | row[j]
if key in pairs:
return True
pairs.add(key)
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]
]
print("true" if ValidCorner(mat) else "false")
using System;
using System.Collections.Generic;
class GfG{
static bool ValidCorner(int[][] mat) {
List<List<short>> rows = new List<List<short>>();
int N = 0;
// Preprocess: Store columns with 1s for each row
foreach (var row in mat) {
List<short> cols = new List<short>();
for (short c = 0; c < row.Length; ++c) {
if (row[c] == 1) cols.Add(c);
}
rows.Add(cols);
N += cols.Count;
}
int sqrtN = (int)Math.Sqrt(N);
HashSet<int> pairs = new HashSet<int>();
for (int r = 0; r < rows.Count; ++r) {
if (rows[r].Count >= sqrtN) {
// Dense row: Check against all previous rows
HashSet<short> cols = new HashSet<short>(rows[r]);
for (int r2 = 0; r2 < r; ++r2) {
int common = 0;
foreach (short c in rows[r2]) {
if (cols.Contains(c)) {
common++;
if (common >= 2) return true; // Early exit
}
}
}
} else {
// Sparse row: Check column pairs
var row = rows[r];
for (int i = 0; i < row.Count; ++i) {
for (int j = i + 1; j < row.Count; ++j) {
int key = (row[i] << 13) | row[j];
if (pairs.Contains(key)) return true;
pairs.Add(key);
}
}
}
}
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}
};
Console.WriteLine(ValidCorner(mat) ? "true" : "false");
}
}
function ValidCorner(mat) {
let rows = [];
let N = 0;
// Preprocess: Store columns with 1s for each row
for (let row of mat) {
let cols = [];
for (let c = 0; c < row.length; c++) {
if (row[c] === 1) cols.push(c);
}
rows.push(cols);
N += cols.length;
}
let sqrtN = Math.floor(Math.sqrt(N));
let pairs = new Set();
for (let r = 0; r < rows.length; r++) {
if (rows[r].length >= sqrtN) {
// Dense row: Check against all previous rows
let cols = new Set(rows[r]);
for (let r2 = 0; r2 < r; r2++) {
let common = 0;
for (let c of rows[r2]) {
if (cols.has(c)) {
common++;
if (common >= 2) return true; // Early exit
}
}
}
} else {
// Sparse row: Check column pairs
let row = rows[r];
for (let i = 0; i < row.length; i++) {
for (let j = i + 1; j < row.length; j++) {
let key = (row[i] << 13) | row[j];
if (pairs.has(key)) return true;
pairs.add(key);
}
}
}
}
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 + r * c * √N + N)
— for preprocessing, dense row comparison, and sparse row column pair checks. In the worst case (N ≈ r*c), it becomes O(r * c* √(r * c))
. where N is the number of 1's and r and c is number rows and columns.
Auxiliary space: O(N),
for storing 1's column indices and column pairs, number of 1's.