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

📅  最后修改于: 2021-09-07 04:54:22             🧑  作者: 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 ,则增加count。

下面是上述方法的实现:

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 Classes Live