给定一个大小为N x M且整数为X的矩阵,任务是查找矩阵中元素和之和等于X的子平方数。
例子:
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.
天真的方法:
解决该问题的最简单方法是生成所有可能的子平方,并检查子平方的所有元素的总和等于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)