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.

22

**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

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 count

if 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 res

if 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)