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

📅  最后修改于: 2021-06-26 22:08:47             🧑  作者: 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


Javascript


输出:
3

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

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。