Count of submatrix with sum X (original) (raw)
Given a matrix **mat[][] of size **n*m and an integer **x, Find the number of **sub-squares in the matrix with sum of elements equal to x.
**Examples:
**Input: mat[][] = [[2, 4, 7, 8, 10], x = 10
[3, 1, 1, 1, 1],
[9, 11, 1, 2, 1],
[12, -17, 1, 1, 1]]
**Output: 3
**Explanation: The sub-squares are colored in the matrix.
**Input: mat[][] = [[3, 3, 5, 3], x = 1
[2, 2, 2, 6],
[11, 2, 2, 4]]
**Output: 0
**Explanation: There are no sub-squares whose sum is 1.
Table of Content
- [Naive Approach] Generate all possible sub-square matrices
- [Expected Approach] Prefix sum with hashing
[Naive Approach] Generate all possible sub-square matrices
Generate all possible sub-squares and check sum of all the elements of the sub-square equals to x. For each square size, it slides a window over all possible top-left positions in the matrix where a square of that size can fit. At each position, it computes the sum of all elements inside the current square using nested loops. If the computed sum is equal to the target value x, it increments the count.
C++ `
#include #include using namespace std;
int countSquare(vector<vector> &mat, int x) {
int count = 0 ;
int n = mat.size() ;
int m = mat[0].size() ;
// Maximum possible size of a square
int maxSize = min(n, m) ;
// Try all possible square sizes
for (int size = 1; size <= maxSize; size++) {
// Loop through all top-left corners of
// squares of this size
for (int i = 0; i <= n - size; i++) {
for (int j = 0; j <= m - size; j++) {
int sum = 0;
// Compute the sum of the current square
for (int p = i; p < i + size; p++) {
for (int q = j; q < j + size; q++) {
sum += mat[p][q];
}
}
// Check if the sum matches the target value x
if (sum == x) {
count++;
}
}
}
}
return count;}
int main() { vector<vector > mat = { {2, 4, 7, 8, 10}, {3, 1, 1, 1, 1}, {9, 11, 1, 2, 1}, {12, -17, 1, 1, 1} };
int x = 10;
int res = countSquare(mat, x);
cout << res << endl;
return 0;}
Java
public class GfG {
public static int countSquare(int[][] mat, int x) {
int count = 0;
int n = mat.length;
int m = mat[0].length;
// Largest possible square size
int maxSize = Math.min(n, m);
// Try all square sizes from 1x1 to maxSize x maxSize
for (int size = 1; size <= maxSize; size++) {
// Slide square of current size across all
// valid top-left positions
for (int i = 0; i <= n - size; i++) {
for (int j = 0; j <= m - size; j++) {
int sum = 0;
// Compute sum of the current square submatrix
for (int p = i; p < i + size; p++) {
for (int q = j; q < j + size; q++) {
sum += mat[p][q];
}
}
// If sum matches the target, increment the count
if (sum == x) {
count++;
}
}
}
}
return count;
}
public static void main(String[] args) {
int[][] mat = {
{2, 4, 7, 8, 10},
{3, 1, 1, 1, 1},
{9, 11, 1, 2, 1},
{12, -17, 1, 1, 1}
};
int x = 10;
int res = countSquare(mat, x);
System.out.println(res);
}}
Python
def countSquare(mat, x):
count = 0
n = len(mat)
m = len(mat[0])
# Largest square size allowed
maxSize = min(n, m)
# Try each square size from 1x1 to max_size x max_size
for size in range(1, maxSize + 1):
# Slide the square over all valid top-left positions
for i in range(n - size + 1):
for j in range(m - size + 1):
total = 0
# Calculate sum of the current square submatrix
for p in range(i, i + size):
for q in range(j, j + size):
total += mat[p][q]
# If the sum equals the target x, count it
if total == x:
count += 1
return countif name == "main": mat = [ [2, 4, 7, 8, 10], [3, 1, 1, 1, 1], [9, 11, 1, 2, 1], [12, -17, 1, 1, 1] ] x = 10
res = countSquare(mat, x)
print(res)C#
using System;
class GfG {
static int countSquare(int[,] mat, int x) {
int count = 0 ;
int n = mat.GetLength(0) ;
int m = mat.GetLength(1) ;
// Largest square possible
int maxSize = Math.Min(n, m) ;
// Try all square sizes from 1x1 to maxSize x maxSize
for (int size = 1; size <= maxSize; size++)
{
// Loop over all valid top-left corners
for (int i = 0; i <= n - size; i++)
{
for (int j = 0; j <= m - size; j++)
{
int sum = 0 ;
// Calculate sum of current square submatrix
for (int p = i; p < i + size; p++)
{
for (int q = j; q < j + size; q++)
{
sum += mat[p, q];
}
}
// Check if the submatrix sum matches target
if (sum == x)
{
count++;
}
}
}
}
return count;
}
static void Main()
{
int[,] mat =
{
{2, 4, 7, 8, 10},
{3, 1, 1, 1, 1},
{9, 11, 1, 2, 1},
{12, -17, 1, 1, 1}
};
int x = 10 ;
int res = countSquare(mat, x) ;
Console.WriteLine(res) ;
}}
JavaScript
function countSquare(mat, x) {
let count = 0;
const n = mat.length;
const m = mat[0].length;
// Largest square size allowed
const maxSize = Math.min(n, m);
// Try all square sizes from 1 to maxSize
for (let size = 1; size <= maxSize; size++) {
// Loop over all valid top-left corners
// for the current square size
for (let i = 0; i <= n - size; i++) {
for (let j = 0; j <= m - size; j++) {
let sum = 0;
// Compute the sum of the current square
for (let p = i; p < i + size; p++) {
for (let q = j; q < j + size; q++) {
sum += mat[p][q];
}
}
// If sum matches the target, increment count
if (sum === x) {
count++;
}
}
}
}
return count;}
// Driver Code const mat = [ [2, 4, 7, 8, 10], [3, 1, 1, 1, 1], [9, 11, 1, 2, 1], [12, -17, 1, 1, 1] ];
const x = 10;
const res = countSquare(mat, x); console.log(res);
`
****Time Complexity:**O(n2 * m2 * min(n,m)), because for each square size, the code checks all possible positions and sums all elements within each square.
****Auxiliary Space:**O(1), since no extra space has been taken__._
[Expected Approach]Prefix sum with hashing
Compute prefix sums row-wise to allow quick calculation of horizontal subarray sums. Then, for every pair of columns i and j, reduce the matrix to a 1D array by summing values in each row between columns i and j. For each such 1D array, maintain a running sum and use a hash map to count how many times a particular prefix sum has occurred. Whenever the difference between the current sum and the target is found in the map, increment the result by that frequency.
C++ ``
#include #include #include using namespace std;
int countSquare(vector<vector>& mat, int x) {
int res = 0 ;
int n = mat.size() ;
int m = mat[0].size() ;
// Compute row-wise prefix sum
vector<vector<int>> rowPrefix = mat;
for (int i = 0; i < n; i++)
for (int j = 1; j < m; j++)
rowPrefix[i][j] += rowPrefix[i][j - 1];
// Maximum square size possible
int maxSize = min(n, m);
// Try each possible square size
for (int size = 1; size <= maxSize; size++) {
// Slide over all column ranges of width = size
for (int i = 0; i <= m - size; i++) {
// Right column index
int j = i + size - 1;
// Compute column sum for `size` consecutive rows
int sum = 0;
for (int row = 0; row < size - 1; row++) {
sum += rowPrefix[row][j] -
(i > 0 ? rowPrefix[row][i - 1] : 0);
}
// Now apply sliding window over rows
for (int row = size - 1; row < n; row++) {
// Add the new row
sum += rowPrefix[row][j] -
(i > 0 ? rowPrefix[row][i - 1] : 0);
// Check if the current square has the required sum
if (sum == x) res++;
// Remove the top row of the previous window
sum -= rowPrefix[row - size + 1][j] -
(i > 0 ? rowPrefix[row - size + 1][i - 1] : 0);
}
}
}
return res;}
int main() { int x = 10;
vector<vector<int>> mat = {
{2, 4, 7, 8, 10},
{3, 1, 1, 1, 1},
{9, 11, 1, 2, 1},
{12, -17, 1, 1, 1}
};
cout << countSquare(mat, x) << endl;
return 0;}
`` Java `
public class GfG { public static int countSquare(int[][] mat, int x) { int res = 0; int n = mat.length; int m = mat[0].length;
// Compute row-wise prefix sum
int[][] rowPrefix = new int[n][m];
for (int i = 0; i < n; i++) {
rowPrefix[i][0] = mat[i][0];
for (int j = 1; j < m; j++) {
rowPrefix[i][j] = rowPrefix[i][j - 1] + mat[i][j];
}
}
int maxSize = Math.min(n, m);
// Try each possible square size
for (int size = 1; size <= maxSize; size++) {
for (int i = 0; i <= m - size; i++) {
int j = i + size - 1;
int sum = 0;
for (int row = 0; row < size - 1; row++) {
sum += rowPrefix[row][j] -
(i > 0 ? rowPrefix[row][i - 1] : 0);
}
for (int row = size - 1; row < n; row++) {
sum += rowPrefix[row][j] -
(i > 0 ? rowPrefix[row][i - 1] : 0);
if (sum == x) res++;
sum -= rowPrefix[row - size + 1][j] -
(i > 0 ? rowPrefix[row - size + 1][i - 1] : 0);
}
}
}
return res;
}
public static void main(String[] args) {
int x = 10;
int[][] mat = {
{2, 4, 7, 8, 10},
{3, 1, 1, 1, 1},
{9, 11, 1, 2, 1},
{12, -17, 1, 1, 1}
};
System.out.println(countSquare(mat, x));
}}
Python
def countSquare(mat, x): res = 0 n = len(mat) m = len(mat[0])
# Compute row-wise prefix sum
rowPrefix = [row[:] for row in mat]
for i in range(n):
for j in range(1, m):
rowPrefix[i][j] += rowPrefix[i][j - 1]
maxSize = min(n, m)
# Try all possible square sizes
for size in range(1, maxSize + 1):
# Try all possible column ranges [i, j] of width 'size'
for i in range(m - size + 1):
j = i + size - 1
total = 0
# Compute sum for top (size - 1) rows of the square window
for row in range(size - 1):
total += rowPrefix[row][j] - \
(rowPrefix[row][i - 1] if i > 0 else 0)
# Slide the square window down row by row
for row in range(size - 1, n):
total += rowPrefix[row][j] - \
(rowPrefix[row][i - 1] if i > 0 else 0)
# Check if the current square has sum x
if total == x:
res += 1
# Remove the top row of the previous window
total -= rowPrefix[row - size + 1][j] - \
(rowPrefix[row - size + 1][i - 1] if i > 0 else 0)
return resif name == "main": mat = [ [2, 4, 7, 8, 10], [3, 1, 1, 1, 1], [9, 11, 1, 2, 1], [12, -17, 1, 1, 1] ]
x = 10
print(countSquare(mat, x))C#
using System; using System.Collections.Generic;
class GfG { static int countSquare(int[,] mat, int x) { int res = 0; int n = mat.GetLength(0); int m = mat.GetLength(1);
// Compute row-wise prefix sum
int[,] rowPrefix = new int[n, m];
for (int i = 0; i < n; i++) {
rowPrefix[i, 0] = mat[i, 0];
for (int j = 1; j < m; j++) {
rowPrefix[i, j] = rowPrefix[i, j - 1] + mat[i, j];
}
}
int maxSize = Math.Min(n, m);
// Try all square sizes
for (int size = 1; size <= maxSize; size++) {
// Slide square window horizontally
for (int i = 0; i <= m - size; i++) {
int j = i + size - 1;
int sum = 0;
// Add top (size - 1) rows initially
for (int row = 0; row < size - 1; row++) {
sum += rowPrefix[row, j] -
(i > 0 ? rowPrefix[row, i - 1] : 0);
}
// Slide window down vertically
for (int row = size - 1; row < n; row++) {
sum += rowPrefix[row, j] -
(i > 0 ? rowPrefix[row, i - 1] : 0);
if (sum == x) res++;
// Remove top row of current square window
sum -= rowPrefix[row - size + 1, j] -
(i > 0 ? rowPrefix[row - size + 1, i - 1] : 0);
}
}
}
return res;
}
static void Main() {
int x = 10;
int[,] mat = {
{ 2, 4, 7, 8, 10 },
{ 3, 1, 1, 1, 1 },
{ 9, 11, 1, 2, 1 },
{ 12, -17, 1, 1, 1 }};
Console.WriteLine(countSquare(mat, x));
}}
JavaScript
function countSquare(mat, x) { let res = 0; const n = mat.length; const m = mat[0].length;
// Compute row-wise prefix sum
const rowPrefix = mat.map(row => row.slice());
for (let i = 0; i < n; i++) {
for (let j = 1; j < m; j++) {
rowPrefix[i][j] += rowPrefix[i][j - 1];
}
}
const maxSize = Math.min(n, m);
// Try all square sizes
for (let size = 1; size <= maxSize; size++) {
// Slide square window horizontally
for (let i = 0; i <= m - size; i++) {
let j = i + size - 1;
let sum = 0;
// Add top (size - 1) rows initially
for (let row = 0; row < size - 1; row++) {
sum += rowPrefix[row][j] -
(i > 0 ? rowPrefix[row][i - 1] : 0);
}
// Slide the window down vertically
for (let row = size - 1; row < n; row++) {
sum += rowPrefix[row][j] -
(i > 0 ? rowPrefix[row][i - 1] : 0);
// Check if current square sum equals target
if (sum === x) res++;
// Subtract top row as window slides down
sum -= rowPrefix[row - size + 1][j] -
(i > 0 ? rowPrefix[row - size + 1][i - 1] : 0);
}
}
}
return res;}
// Driver Code const mat = [ [2, 4, 7, 8, 10], [3, 1, 1, 1, 1], [9, 11, 1, 2, 1], [12, -17, 1, 1, 1] ];
const x = 10; console.log(countSquare(mat, x));
`
**Time Complexity: O(n * m * min(n,m)), because for each possible square size (up to min(n, m)), the code slides a square window of that size across all valid positions in the matrix, doing constant-time work per position.
**Auxiliary Space: O(n*m)
