Count of submatrix with sum X in a given Matrix

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

Below is the implementation of the above approach:



filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 X
int 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 Code
int 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;
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the above approach 
import java.util.*;
class GFG{ 
  
// Size of a column 
static final int m = 5
  
// Function to find the count of submatrix 
// whose sum is X 
static 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 Code 
public 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
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
  
# Size of a column
m = 5
  
# Function to find the count of 
# submatrix whose sum is X
def 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 Code
if __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 
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for the above approach 
using System;
  
class GFG{ 
  
// Size of a column 
static readonly int m = 5; 
  
// Function to find the count of submatrix 
// whose sum is X 
static 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 Code 
public 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
chevron_right

Output: 
3

Time Complexity: O(N * M * log(max(N, M))) 
Auxiliary Space: O(N * M)
 





Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Article Tags :