Maximum size of square such that all submatrices of that size have sum less than K
Last Updated :
11 Feb, 2022
Given an N x M matrix of integers and an integer K, the task is to find the size of the maximum square sub-matrix (S x S), such that all square sub-matrices of the given matrix of that size have a sum less than K.
Examples:
Input: K = 30
mat[N][M] = {{1, 2, 3, 4, 6},
{5, 3, 8, 1, 2},
{4, 6, 7, 5, 5},
{2, 4, 8, 9, 4} };
Output: 2
Explanation:
All Sub-matrices of size 2 x 2
have sum less than 30
Input : K = 100
mat[N][M] = { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
Output: 3
Explanation:
All Sub-matrices of size 3 x 3
have sum less than 100
Naive Approach The basic solution is to choose the size S of the submatrix and find all the submatrices of that size and check that the sum of all sub-matrices is less than the given sum whereas, this can be improved by computing the sum of the matrix using this approach. Therefore, the task will be to choose the maximum size possible and the starting and ending position of every possible sub-matrices. Due to which the overall time complexity will be O(N3).
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define N 4
#define M 5
void preProcess( int mat[N][M],
int aux[N][M])
{
for ( int i = 0; i < M; i++)
aux[0][i] = mat[0][i];
for ( int i = 1; i < N; i++)
for ( int j = 0; j < M; j++)
aux[i][j] = mat[i][j] +
aux[i - 1][j];
for ( int i = 0; i < N; i++)
for ( int j = 1; j < M; j++)
aux[i][j] += aux[i][j - 1];
}
int sumQuery( int aux[N][M], int tli,
int tlj, int rbi, int rbj)
{
int res = aux[rbi][rbj];
if (tli > 0)
res = res - aux[tli - 1][rbj];
if (tlj > 0)
res = res - aux[rbi][tlj - 1];
if (tli > 0 && tlj > 0)
res = res +
aux[tli - 1][tlj - 1];
return res;
}
int maximumSquareSize( int mat[N][M], int K)
{
int aux[N][M];
preProcess(mat, aux);
for ( int i = min(N, M); i >= 1; i--) {
bool satisfies = true ;
for ( int x = 0; x < N; x++) {
for ( int y = 0; y < M; y++) {
if (x + i - 1 <= N - 1 &&
y + i - 1 <= M - 1) {
if (sumQuery(aux, x, y,
x + i - 1, y + i - 1) > K)
satisfies = false ;
}
}
}
if (satisfies == true )
return (i);
}
return 0;
}
int main()
{
int K = 30;
int mat[N][M] = { { 1, 2, 3, 4, 6 },
{ 5, 3, 8, 1, 2 },
{ 4, 6, 7, 5, 5 },
{ 2, 4, 8, 9, 4 } };
cout << maximumSquareSize(mat, K);
return 0;
}
|
Java
class GFG{
static final int N = 4 ;
static final int M = 5 ;
static void preProcess( int [][]mat,
int [][]aux)
{
for ( int i = 0 ; i < M; i++)
aux[ 0 ][i] = mat[ 0 ][i];
for ( int i = 1 ; i < N; i++)
for ( int j = 0 ; j < M; j++)
aux[i][j] = mat[i][j] +
aux[i - 1 ][j];
for ( int i = 0 ; i < N; i++)
for ( int j = 1 ; j < M; j++)
aux[i][j] += aux[i][j - 1 ];
}
static int sumQuery( int [][]aux, int tli,
int tlj, int rbi, int rbj)
{
int res = aux[rbi][rbj];
if (tli > 0 )
res = res - aux[tli - 1 ][rbj];
if (tlj > 0 )
res = res - aux[rbi][tlj - 1 ];
if (tli > 0 && tlj > 0 )
res = res +
aux[tli - 1 ][tlj - 1 ];
return res;
}
static int maximumSquareSize( int [][]mat, int K)
{
int [][]aux = new int [N][M];
preProcess(mat, aux);
for ( int i = Math.min(N, M); i >= 1 ; i--) {
boolean satisfies = true ;
for ( int x = 0 ; x < N; x++) {
for ( int y = 0 ; y < M; y++) {
if (x + i - 1 <= N - 1 &&
y + i - 1 <= M - 1 ) {
if (sumQuery(aux, x, y,
x + i - 1 , y + i - 1 ) > K)
satisfies = false ;
}
}
}
if (satisfies == true )
return (i);
}
return 0 ;
}
public static void main(String[] args)
{
int K = 30 ;
int mat[][] = { { 1 , 2 , 3 , 4 , 6 },
{ 5 , 3 , 8 , 1 , 2 },
{ 4 , 6 , 7 , 5 , 5 },
{ 2 , 4 , 8 , 9 , 4 } };
System.out.print(maximumSquareSize(mat, K));
}
}
|
Python3
N = 4
M = 5
def preProcess(mat, aux):
for i in range (M):
aux[ 0 ][i] = mat[ 0 ][i]
for i in range ( 1 , N):
for j in range (M):
aux[i][j] = (mat[i][j] +
aux[i - 1 ][j])
for i in range (N):
for j in range ( 1 , M):
aux[i][j] + = aux[i][j - 1 ]
def sumQuery(aux, tli, tlj, rbi, rbj):
res = aux[rbi][rbj]
if (tli > 0 ):
res = res - aux[tli - 1 ][rbj]
if (tlj > 0 ):
res = res - aux[rbi][tlj - 1 ]
if (tli > 0 and tlj > 0 ):
res = (res +
aux[tli - 1 ][tlj - 1 ])
return res
def maximumSquareSize(mat, K):
aux = [[ 0 for x in range (M)]
for y in range (N)]
preProcess(mat, aux)
for i in range ( min (N, M), 0 , - 1 ):
satisfies = True
for x in range (N):
for y in range (M) :
if (x + i - 1 < = N - 1 and
y + i - 1 < = M - 1 ):
if (sumQuery(aux, x, y,
x + i - 1 ,
y + i - 1 ) > K):
satisfies = False
if (satisfies = = True ):
return (i)
return 0
if __name__ = = "__main__" :
K = 30
mat = [[ 1 , 2 , 3 , 4 , 6 ],
[ 5 , 3 , 8 , 1 , 2 ],
[ 4 , 6 , 7 , 5 , 5 ],
[ 2 , 4 , 8 , 9 , 4 ]]
print ( maximumSquareSize(mat, K))
|
C#
using System;
public class GFG{
static readonly int N = 4;
static readonly int M = 5;
static void preProcess( int [,]mat,
int [,]aux)
{
for ( int i = 0; i < M; i++)
aux[0,i] = mat[0,i];
for ( int i = 1; i < N; i++)
for ( int j = 0; j < M; j++)
aux[i,j] = mat[i,j] +
aux[i - 1,j];
for ( int i = 0; i < N; i++)
for ( int j = 1; j < M; j++)
aux[i,j] += aux[i,j - 1];
}
static int sumQuery( int [,]aux, int tli,
int tlj, int rbi, int rbj)
{
int res = aux[rbi,rbj];
if (tli > 0)
res = res - aux[tli - 1,rbj];
if (tlj > 0)
res = res - aux[rbi,tlj - 1];
if (tli > 0 && tlj > 0)
res = res +
aux[tli - 1,tlj - 1];
return res;
}
static int maximumSquareSize( int [,]mat, int K)
{
int [,]aux = new int [N,M];
preProcess(mat, aux);
for ( int i = Math.Min(N, M); i >= 1; i--) {
bool satisfies = true ;
for ( int x = 0; x < N; x++) {
for ( int y = 0; y < M; y++) {
if (x + i - 1 <= N - 1 &&
y + i - 1 <= M - 1) {
if (sumQuery(aux, x, y,
x + i - 1, y + i - 1) > K)
satisfies = false ;
}
}
}
if (satisfies == true )
return (i);
}
return 0;
}
public static void Main(String[] args)
{
int K = 30;
int [,]mat = { { 1, 2, 3, 4, 6 },
{ 5, 3, 8, 1, 2 },
{ 4, 6, 7, 5, 5 },
{ 2, 4, 8, 9, 4 } };
Console.Write(maximumSquareSize(mat, K));
}
}
|
Javascript
<script>
let N = 4;
let M = 5;
function preProcess(mat,aux)
{
for (let i = 0; i < M; i++)
aux[0][i] = mat[0][i];
for (let i = 1; i < N; i++)
for (let j = 0; j < M; j++)
aux[i][j] = mat[i][j] +
aux[i - 1][j];
for (let i = 0; i < N; i++)
for (let j = 1; j < M; j++)
aux[i][j] += aux[i][j - 1];
}
function sumQuery(aux,tli,tlj,rbi,rbj)
{
let res = aux[rbi][rbj];
if (tli > 0)
res = res - aux[tli - 1][rbj];
if (tlj > 0)
res = res - aux[rbi][tlj - 1];
if (tli > 0 && tlj > 0)
res = res +
aux[tli - 1][tlj - 1];
return res;
}
function maximumSquareSize(mat,k)
{
let aux = new Array(N);
for (let i=0;i<N;i++)
{
aux[i]= new Array(M);
}
preProcess(mat, aux);
for (let i = Math.min(N, M); i >= 1; i--) {
let satisfies = true ;
for (let x = 0; x < N; x++) {
for (let y = 0; y < M; y++) {
if (x + i - 1 <= N - 1 &&
y + i - 1 <= M - 1) {
if (sumQuery(aux, x, y,
x + i - 1, y + i - 1) > K)
satisfies = false ;
}
}
}
if (satisfies == true )
return (i);
}
return 0;
}
let mat = [[1, 2, 3, 4, 6],
[5, 3, 8, 1, 2],
[4, 6, 7, 5, 5],
[2, 4, 8, 9, 4]];
let K = 30;
document.write(maximumSquareSize(mat, K));
</script>
|
- Time complexity: O(N3)
- Auxiliary Space: O(N2)
Efficient Approach: The key observation is, if a square of side s is the maximum size satisfying the condition, then all sizes smaller than it will satisfy the condition. Using this we can reduce our search space at each step by half which is precisely the idea of Binary Search. Below is the illustration of the steps of the approach:
- Search Space: The search space for this problem will be from [1, min(N, M)]. That is the search space for binary search is defined as –
low = 1
high = min(N, M)
- Next Search Space: In each iteration find the mid of the search space and then Finally, check that all subarrays of that size have the sum less than K. If all subarrays of that size have sum less than K. Then the next search space possible will be in the right of the middle. Otherwise, the next search space possible will be in the left of the middle. That is less than the middle.
- Case 1: Condition when the all the subarrays of size mid have sum less than K. Then –
if checkSubmatrix(mat, mid, K):
low = mid + 1
- Case 2: Condition when the all the subarrays of size mid have sum greater than K. Then –
if not checkSubmatrix(mat, mid, K):
high = mid - 1
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define N 4
#define M 5
void preProcess( int mat[N][M],
int aux[N][M])
{
for ( int i = 0; i < M; i++)
aux[0][i] = mat[0][i];
for ( int i = 1; i < N; i++)
for ( int j = 0; j < M; j++)
aux[i][j] = mat[i][j] +
aux[i - 1][j];
for ( int i = 0; i < N; i++)
for ( int j = 1; j < M; j++)
aux[i][j] += aux[i][j - 1];
}
int sumQuery( int aux[N][M], int tli,
int tlj, int rbi, int rbj)
{
int res = aux[rbi][rbj];
if (tli > 0)
res = res - aux[tli - 1][rbj];
if (tlj > 0)
res = res - aux[rbi][tlj - 1];
if (tli > 0 && tlj > 0)
res = res + aux[tli - 1][tlj - 1];
return res;
}
bool check( int mid, int aux[N][M],
int K)
{
bool satisfies = true ;
for ( int x = 0; x < N; x++) {
for ( int y = 0; y < M; y++) {
if (x + mid - 1 <= N - 1 &&
y + mid - 1 <= M - 1) {
if (sumQuery(aux, x, y,
x + mid - 1, y + mid - 1) > K)
satisfies = false ;
}
}
}
return (satisfies == true );
}
int maximumSquareSize( int mat[N][M],
int K)
{
int aux[N][M];
preProcess(mat, aux);
int low = 1, high = min(N, M);
int mid;
while (high - low > 1) {
mid = (low + high) / 2;
if (check(mid, aux, K)) {
low = mid;
}
else
high = mid;
}
if (check(high, aux, K))
return high;
return low;
}
int main()
{
int K = 30;
int mat[N][M] = { { 1, 2, 3, 4, 6 },
{ 5, 3, 8, 1, 2 },
{ 4, 6, 7, 5, 5 },
{ 2, 4, 8, 9, 4 } };
cout << maximumSquareSize(mat, K);
return 0;
}
|
Java
class GFG{
static final int N = 4 ;
static final int M = 5 ;
static void preProcess( int [][]mat,
int [][]aux)
{
for ( int i = 0 ; i < M; i++)
aux[ 0 ][i] = mat[ 0 ][i];
for ( int i = 1 ; i < N; i++)
for ( int j = 0 ; j < M; j++)
aux[i][j] = mat[i][j] +
aux[i - 1 ][j];
for ( int i = 0 ; i < N; i++)
for ( int j = 1 ; j < M; j++)
aux[i][j] += aux[i][j - 1 ];
}
static int sumQuery( int [][]aux, int tli,
int tlj, int rbi, int rbj)
{
int res = aux[rbi][rbj];
if (tli > 0 )
res = res - aux[tli - 1 ][rbj];
if (tlj > 0 )
res = res - aux[rbi][tlj - 1 ];
if (tli > 0 && tlj > 0 )
res = res + aux[tli - 1 ][tlj - 1 ];
return res;
}
static boolean check( int mid, int [][]aux,
int K)
{
boolean satisfies = true ;
for ( int x = 0 ; x < N; x++)
{
for ( int y = 0 ; y < M; y++)
{
if (x + mid - 1 <= N - 1 &&
y + mid - 1 <= M - 1 )
{
if (sumQuery(aux, x, y,
x + mid - 1 ,
y + mid - 1 ) > K)
satisfies = false ;
}
}
}
return (satisfies == true );
}
static int maximumSquareSize( int [][]mat,
int K)
{
int [][]aux = new int [N][M];
preProcess(mat, aux);
int low = 1 , high = Math.min(N, M);
int mid;
while (high - low > 1 )
{
mid = (low + high) / 2 ;
if (check(mid, aux, K))
{
low = mid;
}
else
high = mid;
}
if (check(high, aux, K))
return high;
return low;
}
public static void main(String[] args)
{
int K = 30 ;
int [][]mat = { { 1 , 2 , 3 , 4 , 6 },
{ 5 , 3 , 8 , 1 , 2 },
{ 4 , 6 , 7 , 5 , 5 },
{ 2 , 4 , 8 , 9 , 4 } };
System.out.print(maximumSquareSize(mat, K));
}
}
|
Python3
def preProcess(mat, aux):
for i in range ( 5 ):
aux[ 0 ][i] = mat[ 0 ][i]
for i in range ( 1 , 4 ):
for j in range ( 5 ):
aux[i][j] = (mat[i][j] +
aux[i - 1 ][j])
for i in range ( 4 ):
for j in range ( 1 , 5 ):
aux[i][j] + = aux[i][j - 1 ]
return aux
def sumQuery(aux, tli, tlj, rbi, rbj):
res = aux[rbi][rbj]
if (tli > 0 ):
res = res - aux[tli - 1 ][rbj]
if (tlj > 0 ):
res = res - aux[rbi][tlj - 1 ]
if (tli > 0 and tlj > 0 ):
res = res + aux[tli - 1 ][tlj - 1 ]
return res
def check(mid, aux, K):
satisfies = True
for x in range ( 4 ):
for y in range ( 5 ):
if (x + mid - 1 < = 4 - 1 and
y + mid - 1 < = 5 - 1 ):
if (sumQuery(aux, x, y,
x + mid - 1 ,
y + mid - 1 ) > K):
satisfies = False
return True if satisfies = = True else False
def maximumSquareSize(mat, K):
aux = [[ 0 for i in range ( 5 )]
for i in range ( 4 )]
aux = preProcess(mat, aux)
low , high = 1 , min ( 4 , 5 )
mid = 0
while (high - low > 1 ):
mid = (low + high) / / 2
if (check(mid, aux, K)):
low = mid
else :
high = mid
if (check(high, aux, K)):
return high
return low
if __name__ = = '__main__' :
K = 30
mat = [ [ 1 , 2 , 3 , 4 , 6 ],
[ 5 , 3 , 8 , 1 , 2 ],
[ 4 , 6 , 7 , 5 , 5 ],
[ 2 , 4 , 8 , 9 , 4 ] ]
print (maximumSquareSize(mat, K))
|
C#
using System;
class GFG{
static readonly int N = 4;
static readonly int M = 5;
static void preProcess( int [,]mat,
int [,]aux)
{
for ( int i = 0; i < M; i++)
aux[0, i] = mat[0, i];
for ( int i = 1; i < N; i++)
for ( int j = 0; j < M; j++)
aux[i, j] = mat[i, j] +
aux[i - 1, j];
for ( int i = 0; i < N; i++)
for ( int j = 1; j < M; j++)
aux[i, j] += aux[i, j - 1];
}
static int sumQuery( int [,]aux, int tli,
int tlj, int rbi, int rbj)
{
int res = aux[rbi, rbj];
if (tli > 0)
res = res - aux[tli - 1, rbj];
if (tlj > 0)
res = res - aux[rbi, tlj - 1];
if (tli > 0 && tlj > 0)
res = res + aux[tli - 1, tlj - 1];
return res;
}
static bool check( int mid, int [,]aux,
int K)
{
bool satisfies = true ;
for ( int x = 0; x < N; x++)
{
for ( int y = 0; y < M; y++)
{
if (x + mid - 1 <= N - 1 &&
y + mid - 1 <= M - 1)
{
if (sumQuery(aux, x, y,
x + mid - 1,
y + mid - 1) > K)
satisfies = false ;
}
}
}
return (satisfies == true );
}
static int maximumSquareSize( int [,]mat,
int K)
{
int [,]aux = new int [N, M];
preProcess(mat, aux);
int low = 1, high = Math.Min(N, M);
int mid;
while (high - low > 1)
{
mid = (low + high) / 2;
if (check(mid, aux, K))
{
low = mid;
}
else
high = mid;
}
if (check(high, aux, K))
return high;
return low;
}
public static void Main(String[] args)
{
int K = 30;
int [,]mat = { { 1, 2, 3, 4, 6 },
{ 5, 3, 8, 1, 2 },
{ 4, 6, 7, 5, 5 },
{ 2, 4, 8, 9, 4 } };
Console.Write(maximumSquareSize(mat, K));
}
}
|
Javascript
<script>
let N = 4;
let M = 5;
function preProcess(mat,aux)
{
for (let i = 0; i < M; i++)
aux[0][i] = mat[0][i];
for (let i = 1; i < N; i++)
for (let j = 0; j < M; j++)
aux[i][j] = mat[i][j] +
aux[i - 1][j];
for (let i = 0; i < N; i++)
for (let j = 1; j < M; j++)
aux[i][j] += aux[i][j - 1];
}
function sumQuery(aux,tli,tlj,rbi,rbj)
{
let res = aux[rbi][rbj];
if (tli > 0)
res = res - aux[tli - 1][rbj];
if (tlj > 0)
res = res - aux[rbi][tlj - 1];
if (tli > 0 && tlj > 0)
res = res + aux[tli - 1][tlj - 1];
return res;
}
function check(mid,aux,K)
{
let satisfies = true ;
for (let x = 0; x < N; x++)
{
for (let y = 0; y < M; y++)
{
if (x + mid - 1 <= N - 1 &&
y + mid - 1 <= M - 1)
{
if (sumQuery(aux, x, y,
x + mid - 1,
y + mid - 1) > K)
satisfies = false ;
}
}
}
return (satisfies == true );
}
function maximumSquareSize(mat,K)
{
let aux = new Array(N);
for (let i=0;i<N;i++)
{
aux[i]= new Array(M);
}
preProcess(mat, aux);
let low = 1, high = Math.min(N, M);
let mid;
while (high - low > 1)
{
mid = Math.floor((low + high) / 2);
if (check(mid, aux, K))
{
low = mid;
}
else
high = mid;
}
if (check(high, aux, K))
return high;
return low;
}
let K = 30;
let mat = [[1, 2, 3, 4, 6 ],
[ 5, 3, 8, 1, 2 ],
[ 4, 6, 7, 5, 5 ],
[ 2, 4, 8, 9, 4 ] ];
document.write(maximumSquareSize(mat, K));
</script>
|
Performance Analysis:
- Time Complexity: O(N2 * log(N) )
- Auxiliary Space: O(N2)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...