📜  给定矩阵中总和为X的子矩阵的计数

📅  最后修改于: 2021-04-24 21:23:59             🧑  作者: Mango

给定一个大小为N x M且整数为X矩阵,任务是查找矩阵中元素和之和等于X的子平方数。
例子:

天真的方法:
解决该问题的最简单方法是生成所有可能的子平方,并检查子平方的所有元素的总和等于X。
时间复杂度: O(N 3 * M 3 )
辅助空间: O(1)

高效方法:要优化上述简单方法,必须将所有矩阵中所有元素的总和包括在内,直到必须制作出每个像元为止。步骤如下:

  • O(N * M)的计算复杂度预先计算所有矩形的总和,其左上角为(0,0),右下角为(i,j)。
  • 现在,可以观察到,对于每个左上角,总和X最多可以有一个正方形,因为矩阵的元素为正。
  • 记住这一点,我们可以使用二进制搜索来检查是否存在一个平方和为X的平方。
  • 对于矩阵中的每个单元格(i,j) ,将其固定为子正方形的左上角。然后,以(i,j)为左上角遍历所有可能的子正方形,如果sum等于X或不等于X ,则增加计数。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
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;
}


Java
// 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


Python3
# 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


C#
// 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


输出:
3

时间复杂度: O(N * M * log(max(N,M)))
辅助空间: O(N * M)