给定两个分别为N和M的二进制数组A []和B [] ,任务是在通过将两个数组相乘生成的矩阵C [] []中找到由1组成的区域K的矩形数。这样, C [i] [j] = A [i] * B [j] (1 < i < n,1 < j < m)。
例子:
Input: N= 3, M = 3, A[] = {1, 1, 0}, B[] = {0, 1, 1}, K = 2
Output: 4
Explanation: C[][] = {{0, 1, 1}, {0, 1, 1}, {0, 0, 0}}
Therefore, there are 4 possible rectangles of area 2 from the matrix.
Input: N = 4, M = 2, A[] = {0, 0, 1, 1}, B[] = {1, 0, 1}, K = 2
Output: 2
Explanation: C[][] = {{0, 0, 0}, {0, 0, 0}, {1, 0, 1}, {1, 0, 1}}
Therefore, there are 2 possible rectangles of area 2 in the matrix.
天真的方法:解决问题的最简单方法是通过将两个数组相乘生成所需的矩阵,对于区域K的每个可能的矩形,检查其是否仅由1组成。
时间复杂度: O(N * M * K)
辅助空间: O(N * M)
高效方法:为了优化上述方法,需要进行以下观察而不是生成矩阵:
- The area of a rectangle is equal to the product of its length and breadth.
- Using this property, visualize the rectangle as a submatrix which contains only 1s. Therefore, this submatrix is the result of the product of two subarrays of length a, b where a * b = K.
- Since the submatrix contains only 1‘s, it is obvious that these two subarrays also contain only 1‘s in them.
因此,问题减少到从数组A []和B []中找到仅包含所有可能长度的1的子数组,这些子数组是K的适当除数。请按照以下步骤解决问题:
- 预先计算可能的子数组的数量。
- 遍历K的所有除数,并针对每个可能的对( p,q )(其中p * q = K) ,检查A []和B []中是否存在长度为p,q的子数组。
- 相应地增加可能的此类子数组的数量,最后打印获得的数量。
下面是上述方法的实现:
C++
0 1 1 0 1 1 0 1 1 0 1 1
0 1 1 0 1 1 0 1 1 0 1 1
0 0 0 0 0 0 0 0 0 0 0 0
Java
0 0 0 0 0 0
0 0 0 0 0 0
1 0 1 1 0 1
1 0 1 1 0 1
Python3
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to find the subarrays of
// all possible lengths made up of only 1s
vector findSubarrays(vector& a)
{
int n = a.size();
// Stores the frequency
// of the subarrays
vector freq(n + 1);
int count = 0;
for (int i = 0; i < n; i++) {
if (a[i] == 0) {
// Check if the previous
// value was also 0
if (count == 0)
continue;
// If the previous value was 1
else {
int value = count;
for (int j = 1; j <= count; j++) {
// Find the subarrays of
// each size from 1 to count
freq[j] += value;
value--;
}
count = 0;
}
}
else
count++;
}
// If A[] is of the form ....111
if (count > 0) {
int value = count;
for (int j = 1; j <= count; j++) {
freq[j] += value;
value--;
}
}
return freq;
}
// Function to find the count
// of all possible rectangles
void countRectangles(vector& a,
vector& b, int K)
{
// Size of each of the arrays
int n = a.size();
int m = b.size();
// Stores the count of subarrays
// of each size consisting of
// only 1s from array A[]
vector subA
= findSubarrays(a);
// Stores the count of subarrays
// of each size consisting of
// only 1s from array B[]
vector subB
= findSubarrays(b);
int total = 0;
// Iterating over all subarrays
// consisting of only 1s in A[]
for (int i = 1; i < subA.size(); i++) {
// If i is a factor of K, then
// there is a subarray of size K/i in B[]
if (K % i == 0 and (K / i) <= m) {
total = total + subA[i] * subB[K / i];
}
}
cout << total;
}
// Driver Code
int main()
{
vector a = { 0, 0, 1, 1 };
vector b = { 1, 0, 1 };
int K = 2;
countRectangles(a, b, K);
return 0;
}
C#
// Java Program to implement
// the above approach
class GFG{
// Function to find the subarrays of
// all possible lengths made up of only 1s
static int[] findSubarrays(int[] a)
{
int n = a.length;
// Stores the frequency
// of the subarrays
int[] freq = new int[n + 1];
int count = 0;
for (int i = 0; i < n; i++)
{
if (a[i] == 0)
{
// Check if the previous
// value was also 0
if (count == 0)
continue;
// If the previous value was 1
else
{
int value = count;
for (int j = 1; j <= count; j++)
{
// Find the subarrays of
// each size from 1 to count
freq[j] += value;
value--;
}
count = 0;
}
}
else
count++;
}
// If A[] is of the form ....111
if (count > 0)
{
int value = count;
for (int j = 1; j <= count; j++)
{
freq[j] += value;
value--;
}
}
return freq;
}
// Function to find the count
// of all possible rectangles
static void countRectangles(int[] a, int[] b, int K)
{
// Size of each of the arrays
int n = a.length;
int m = b.length;
// Stores the count of subarrays
// of each size consisting of
// only 1s from array A[]
int[] subA = findSubarrays(a);
// Stores the count of subarrays
// of each size consisting of
// only 1s from array B[]
int[] subB = findSubarrays(b);
int total = 0;
// Iterating over all subarrays
// consisting of only 1s in A[]
for (int i = 1; i < subA.length; i++)
{
// If i is a factor of K, then
// there is a subarray of size K/i in B[]
if (K % i == 0 && (K / i) <= m)
{
total = total + subA[i] * subB[K / i];
}
}
System.out.print(total);
}
// Driver Code
public static void main(String[] args)
{
int[] a = {0, 0, 1, 1};
int[] b = {1, 0, 1};
int K = 2;
countRectangles(a, b, K);
}
}
// This code is contributed by shikhasingrajput
# Python3 program to implement
# the above approach
# Function to find the subarrays of
# all possible lengths made up of only 1s
def findSubarrays(a):
n = len(a)
# Stores the frequency
# of the subarrays
freq = [0] * (n + 1)
count = 0
for i in range(n):
if (a[i] == 0):
# Check if the previous
# value was also 0
if (count == 0):
continue
# If the previous value was 1
else:
value = count
for j in range(1, count + 1):
# Find the subarrays of
# each size from 1 to count
freq[j] += value
value -= 1
count = 0
else:
count += 1
# If A[] is of the form ....111
if (count > 0):
value = count
for j in range(1, count + 1):
freq[j] += value
value -= 1
return freq
# Function to find the count
# of all possible rectangles
def countRectangles(a, b, K):
# Size of each of the arrays
n = len(a)
m = len(b)
# Stores the count of subarrays
# of each size consisting of
# only 1s from array A[]
subA = []
subA = findSubarrays(a)
# Stores the count of subarrays
# of each size consisting of
# only 1s from array B[]
subB = []
subB = findSubarrays(b)
total = 0
# Iterating over all subarrays
# consisting of only 1s in A[]
for i in range(1, len(subA)):
# If i is a factor of K, then
# there is a subarray of size K/i in B[]
if (K % i == 0 and (K // i) <= m):
total = total + subA[i] * subB[K // i]
print(total)
# Driver Code
a = [ 0, 0, 1, 1 ]
b = [ 1, 0, 1 ]
K = 2
countRectangles(a, b, K)
# This code is contributed by code_hunt
时间复杂度: O(D)* O(N + M),其中D是K的除数。
辅助空间: O(N + M)