Count of submatrix with sum X in a given Matrix - GeeksforGeeks

05 May, 2021
Given a matrix of size N x M and an integer X, the task is to find the number of sub-squares in the matrix with sum of elements equal to X.Examples:  
Input: N = 4, M = 5, X = 10, arr[][]={{2, 4, 3, 2, 10}, {3, 1, 1, 1, 5}, {1, 1, 2, 1, 4}, {2, 1, 1, 1, 3}} Output: 3 Explanation: {10}, {{2, 4}, {3, 1}} and {{1, 1, 1}, {1, 2, 1}, {1, 1, 1}} are subsquares with sum 10.Input: N = 3, M = 4, X = 8, arr[][]={{3, 1, 5, 3}, {2, 2, 2, 6}, {1, 2, 2, 4}} Output: 2 Explanation: Sub-squares {{2, 2}, {2, 2}} and {{3, 1}, {2, 2}} have sum 8.  
 
Naive Approach: The simplest approach to solve the problem is to generate all possible sub-squares and check sum of all the elements of the sub-square equals to X.Time Complexity: O(N3 * M3) Auxiliary Space: O(1)Efficient Approach: To optimize the above naive approach the sum of all the element of all the matrix till each cell has to be made. Below are the steps:
Precalculate the sum of all rectangles with its upper left corner at (0, 0) and lower right at (i, j) in O(N * M) computational complexity.
Now, it can be observed that, for every upper left corner, there can be at most one square with sum X since elements of the matrix are positive.
Keeping this in mind we can use binary search to check if there exists a square with sum X.
For every cell (i, j) in the matrix, fix it as the upper left corner of the subsquare. Then, traverse over all possible subsquares with (i, j) as the upper left corner and increase count if sum is equal to X or not.  
Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ program for the above approach#include <bits/stdc++.h>using namespace std; // Size of a column#define m 5 // Function to find the count of submatrix// whose sum is Xint countSubsquare(int arr[][m],                   int n, int X){    int dp[n + 1][m + 1];     memset(dp, 0, sizeof(dp));     // Copying arr to dp and making    // it indexed 1    for (int i = 0; i < n; i++) {         for (int j = 0; j < m; j++) {             dp[i + 1][j + 1] = arr[i][j];        }    }     // Precalculate and store the sum    // of all rectangles with upper    // left corner at (0, 0);    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {             // Calculating sum in            // a 2d grid            dp[i][j] += dp[i - 1][j]                        + dp[i][j - 1]                        - dp[i - 1][j - 1];        }    }     // Stores the answer    int cnt = 0;     for (int i = 1; i <= n; i++) {         for (int j = 1; j <= m; j++) {             // Fix upper left corner            // at {i, j} and perform            // binary search on all            // such possible squares             // Minimum length of square            int lo = 1;             // Maximum length of square            int hi = min(n - i, m - j) + 1;             // Flag to set if sub-square            // with sum X is found            bool found = false;             while (lo <= hi) {                int mid = (lo + hi) / 2;                 // Calculate lower                // right index if upper                // right corner is at {i, j}                int ni = i + mid - 1;                int nj = j + mid - 1;                 // Calculate the sum of                // elements in the submatrix                // with upper left column                // {i, j} and lower right                // column at {ni, nj};                int sum = dp[ni][nj]                          - dp[ni][j - 1]                          - dp[i - 1][nj]                          + dp[i - 1][j - 1];                 if (sum >= X) {                     // If sum X is found                    if (sum == X) {                        found = true;                    }                     hi = mid - 1;                     // If sum > X, then size of                    // the square with sum X                    // must be less than mid                }                else {                     // If sum < X, then size of                    // the square with sum X                    // must be greater than mid                    lo = mid + 1;                }            }             // If found, increment            // count by 1;            if (found == true) {                cnt++;            }        }    }    return cnt;} // Driver Codeint main(){    int N = 4, X = 10;     // Given Matrix arr[][]    int arr[N][m] = { { 2, 4, 3, 2, 10 },                      { 3, 1, 1, 1, 5 },                      { 1, 1, 2, 1, 4 },                      { 2, 1, 1, 1, 3 } };     // Function Call    cout << countSubsquare(arr, N, X)         << endl;     return 0;}
// Java program for the above approachimport java.util.*;class GFG{ // Size of a columnstatic final int m = 5; // Function to find the count of submatrix// whose sum is Xstatic int countSubsquare(int arr[][],                          int n, int X){    int [][]dp = new int[n + 1][m + 1];     // Copying arr to dp and making    // it indexed 1    for (int i = 0; i < n; i++)    {        for (int j = 0; j < m; j++)        {            dp[i + 1][j + 1] = arr[i][j];        }    }     // Precalculate and store the sum    // of all rectangles with upper    // left corner at (0, 0);    for (int i = 1; i <= n; i++)    {        for (int j = 1; j <= m; j++)        {             // Calculating sum in            // a 2d grid            dp[i][j] += dp[i - 1][j] +                          dp[i][j - 1] -                          dp[i - 1][j - 1];        }    }     // Stores the answer    int cnt = 0;     for (int i = 1; i <= n; i++)    {        for (int j = 1; j <= m; j++)        {             // Fix upper left corner            // at {i, j} and perform            // binary search on all            // such possible squares             // Minimum length of square            int lo = 1;             // Maximum length of square            int hi = Math.min(n - i, m - j) + 1;             // Flag to set if sub-square            // with sum X is found            boolean found = false;             while (lo <= hi)            {                int mid = (lo + hi) / 2;                 // Calculate lower                // right index if upper                // right corner is at {i, j}                int ni = i + mid - 1;                int nj = j + mid - 1;                 // Calculate the sum of                // elements in the submatrix                // with upper left column                // {i, j} and lower right                // column at {ni, nj};                int sum = dp[ni][nj] -                            dp[ni][j - 1] -                          dp[i - 1][nj] +                          dp[i - 1][j - 1];                 if (sum >= X)                {                     // If sum X is found                    if (sum == X)                    {                        found = true;                    }                     hi = mid - 1;                     // If sum > X, then size of                    // the square with sum X                    // must be less than mid                }                else                {                     // If sum < X, then size of                    // the square with sum X                    // must be greater than mid                    lo = mid + 1;                }            }             // If found, increment            // count by 1;            if (found == true)            {                cnt++;            }        }    }    return cnt;} // Driver Codepublic static void main(String[] args){    int N = 4, X = 10;     // Given Matrix arr[][]    int arr[][] = { { 2, 4, 3, 2, 10 },                    { 3, 1, 1, 1, 5 },                    { 1, 1, 2, 1, 4 },                    { 2, 1, 1, 1, 3 } };     // Function Call    System.out.print(countSubsquare(arr, N, X) + "\n");}} // This code is contributed by sapnasingh4991
# Python3 program for the above approach # Size of a columnm = 5 # Function to find the count of# submatrix whose sum is Xdef countSubsquare(arr, n, X):         dp = [[ 0 for x in range(m + 1)]              for y in range(n + 1)]     # Copying arr to dp and making    # it indexed 1    for i in range(n):        for j in range(m):            dp[i + 1][j + 1] = arr[i][j]     # Precalculate and store the sum    # of all rectangles with upper    # left corner at (0, 0);    for i in range(1, n + 1):        for j in range(1, m + 1):                         # Calculating sum in            # a 2d grid            dp[i][j] += (dp[i - 1][j] +                         dp[i][j - 1] -                         dp[i - 1][j - 1])     # Stores the answer    cnt = 0     for i in range(1, n + 1):        for j in range(1, m + 1):                         # Fix upper left corner            # at {i, j} and perform            # binary search on all            # such possible squares             # Minimum length of square            lo = 1             # Maximum length of square            hi = min(n - i, m - j) + 1             # Flag to set if sub-square            # with sum X is found            found = False             while (lo <= hi):                mid = (lo + hi) // 2                 # Calculate lower right                # index if upper right                # corner is at {i, j}                ni = i + mid - 1                nj = j + mid - 1                 # Calculate the sum of                # elements in the submatrix                # with upper left column                # {i, j} and lower right                # column at {ni, nj};                sum = (dp[ni][nj] -                       dp[ni][j - 1] -                       dp[i - 1][nj] +                       dp[i - 1][j - 1])                 if (sum >= X):                                         # If sum X is found                    if (sum == X):                        found = True                     hi = mid - 1                     # If sum > X, then size of                    # the square with sum X                    # must be less than mid                else:                     # If sum < X, then size of                    # the square with sum X                    # must be greater than mid                    lo = mid + 1             # If found, increment            # count by 1;            if (found == True):                cnt += 1    return cnt # Driver Codeif __name__ =="__main__":     N, X = 4, 10     # Given matrix arr[][]    arr = [ [ 2, 4, 3, 2, 10 ],            [ 3, 1, 1, 1, 5 ],            [ 1, 1, 2, 1, 4 ],            [ 2, 1, 1, 1, 3 ] ]     # Function call    print(countSubsquare(arr, N, X)) # This code is contributed by chitranayal
// C# program for the above approachusing System; class GFG{ // Size of a columnstatic readonly int m = 5; // Function to find the count of submatrix// whose sum is Xstatic int countSubsquare(int [,]arr,                          int n, int X){    int [,]dp = new int[n + 1, m + 1];     // Copying arr to dp and making    // it indexed 1    for(int i = 0; i < n; i++)    {        for(int j = 0; j < m; j++)        {            dp[i + 1, j + 1] = arr[i, j];        }    }     // Precalculate and store the sum    // of all rectangles with upper    // left corner at (0, 0);    for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= m; j++)        {             // Calculating sum in            // a 2d grid            dp[i, j] += dp[i - 1, j] +                        dp[i, j - 1] -                        dp[i - 1, j - 1];        }    }     // Stores the answer    int cnt = 0;     for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= m; j++)        {             // Fix upper left corner            // at {i, j} and perform            // binary search on all            // such possible squares             // Minimum length of square            int lo = 1;             // Maximum length of square            int hi = Math.Min(n - i, m - j) + 1;             // Flag to set if sub-square            // with sum X is found            bool found = false;             while (lo <= hi)            {                int mid = (lo + hi) / 2;                 // Calculate lower                // right index if upper                // right corner is at {i, j}                int ni = i + mid - 1;                int nj = j + mid - 1;                 // Calculate the sum of                // elements in the submatrix                // with upper left column                // {i, j} and lower right                // column at {ni, nj};                int sum = dp[ni, nj] -                          dp[ni, j - 1] -                          dp[i - 1, nj] +                          dp[i - 1, j - 1];                 if (sum >= X)                {                     // If sum X is found                    if (sum == X)                    {                        found = true;                    }                     hi = mid - 1;                     // If sum > X, then size of                    // the square with sum X                    // must be less than mid                }                else                {                     // If sum < X, then size of                    // the square with sum X                    // must be greater than mid                    lo = mid + 1;                }            }             // If found, increment            // count by 1;            if (found == true)            {                cnt++;            }        }    }    return cnt;} // Driver Codepublic static void Main(String[] args){    int N = 4, X = 10;     // Given Matrix [,]arr    int [,]arr = { { 2, 4, 3, 2, 10 },                   { 3, 1, 1, 1, 5 },                   { 1, 1, 2, 1, 4 },                   { 2, 1, 1, 1, 3 } };     // Function call    Console.Write(countSubsquare(arr, N, X) + "\n");}} // This code is contributed by amal kumar choubey
<script> // Javascript program for the above approach     // Size of a column     var m = 5;     // Function to find the count of submatrix    // whose sum is X    function countSubsquare(arr , n , X) {        var dp = Array(n + 1);        for(var i =0;i<n+1;i++)        dp[i] = Array(m + 1).fill(0);         // Copying arr to dp and making        // it indexed 1        for (i = 0; i < n; i++) {            for (j = 0; j < m; j++) {                dp[i + 1][j + 1] = arr[i][j];            }        }         // Precalculate and store the sum        // of all rectangles with upper        // left corner at (0, 0);        for (i = 1; i <= n; i++) {            for (j = 1; j <= m; j++) {                 // Calculating sum in                // a 2d grid                dp[i][j] += dp[i - 1][j] +                dp[i][j - 1] - dp[i - 1][j - 1];            }        }         // Stores the answer        var cnt = 0;         for (i = 1; i <= n; i++) {            for (j = 1; j <= m; j++) {                 // Fix upper left corner                // at {i, j} and perform                // binary search on all                // such possible squares                 // Minimum length of square                var lo = 1;                 // Maximum length of square                var hi = Math.min(n - i, m - j) + 1;                 // Flag to set if sub-square                // with sum X is found                var found = false;                 while (lo <= hi) {                    var mid = parseInt((lo + hi) / 2);                     // Calculate lower                    // right index if upper                    // right corner is at {i, j}                    var ni = i + mid - 1;                    var nj = j + mid - 1;                     // Calculate the sum of                    // elements in the submatrix                    // with upper left column                    // {i, j} and lower right                    // column at {ni, nj];                    var sum = dp[ni][nj] - dp[ni][j - 1] -                    dp[i - 1][nj] + dp[i - 1][j - 1];                     if (sum >= X) {                         // If sum X is found                        if (sum == X) {                            found = true;                        }                         hi = mid - 1;                         // If sum > X, then size of                        // the square with sum X                        // must be less than mid                    } else {                         // If sum < X, then size of                        // the square with sum X                        // must be greater than mid                        lo = mid + 1;                    }                }                 // If found, increment                // count by 1;                if (found == true) {                    cnt++;                }            }        }        return cnt;    }     // Driver Code             var N = 4, X = 10;         // Given Matrix arr        var arr = [ [ 2, 4, 3, 2, 10 ],                    [ 3, 1, 1, 1, 5 ],                    [ 1, 1, 2, 1, 4 ],                    [ 2, 1, 1, 1, 3 ] ];         // Function Call        document.write(countSubsquare(arr, N, X) + "<br/>"); // This code contributed by umadevi9616 </script>
3
 
Time Complexity: O(N * M * log(max(N, M))) Auxiliary Space: O(N * M) 
ukasp
sapnasingh4991
Amal Kumar Choubey
umadevi9616
prefix-sum
submatrix
Competitive Programming
Dynamic Programming
Mathematical
Matrix
Searching
prefix-sum
Searching
Dynamic Programming
Mathematical
Matrix
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Bits manipulation (Important tactics)
Modulo 10^9+7 (1000000007)
Prefix Sum Array - Implementation and Applications in Competitive Programming
Formatted output in Java
Breadth First Traversal ( BFS ) on a 2D array
0-1 Knapsack Problem | DP-10
Largest Sum Contiguous Subarray
Longest Common Subsequence | DP-4
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16