📌  相关文章
📜  从具有至少K对相等元素对的两个数组中选择大小相等的子数组的方式数量

📅  最后修改于: 2021-06-26 23:44:00             🧑  作者: Mango

给定两个数组A []B []以及整数K ,任务是找到选择两个大小相同的子数组的方式的数目,一个从A到另一个,从B到另一个,使得子数组至少具有K个相等的元素对。 (即两个选定子阵列中的对数(A [i],B [j]),使得A [i] = B [j]> = K)。

例子:

方法:

  • 与其将两个数组分开处理,不如将它们以二进制矩阵的形式进行组合,从而:
mat[i][j] = 0, if A[i] != B[j]
          = 1, if A[i] = B[j]
  • 现在,如果我们考虑该矩阵的任何子矩阵,例如P×Q大小,则基本上是A大小为P的子数组和B大小为Q的子数组的组合。由于我们只想检查大小相等的子数组,我们将仅考虑正方形子矩阵。
  • 让我们考虑一个正方形子矩阵,其左上角为(i,j),右下角为(i + size ,, j + size)。这等效于考虑子数组A [i:i +大小]和B [j:j +大小]。可以观察到,如果这两个子阵列将有x对相等的元素,那么子矩阵中将有x 1个。
  • 因此,遍历矩阵(i,j)的所有元素,并将它们视为正方形的右下角。现在,一种方法是遍历子矩阵的所有可能的大小,并找到总和> = k的大小,但这会降低效率。可以观察到,如果说以(i,j)为右下角的S x S子矩阵的总和> = k,则所有大小> = S和(i,j)为右下角的正方形子矩阵都将遵循财产。
  • 因此,我们无需对每个(i,j)上的所有大小进行迭代,而是仅对平方子矩阵的大小进行二进制搜索,并找到最小大小S,使得其总和> = K,然后简单地将矩阵与更大的边长。
    可以参考本文,了解如何使用2D前缀总和在恒定时间内评估子矩阵总和。

下面是上述方法的实现:

C++
// C++ implementation to count the
// number of ways to select equal
// sized subarrays such that they
// have atleast K common elements
 
#include 
 
using namespace std;
 
// 2D prefix sum for submatrix
// sum query for matrix
int prefix_2D[2005][2005];
 
// Function to find the prefix sum
// of the matrix from i and j
int subMatrixSum(int i, int j, int len)
{
    return prefix_2D[i][j] -
           prefix_2D[i][j - len] -
           prefix_2D[i - len][j] +
           prefix_2D[i - len][j - len];
}
 
// Function to count the number of ways
// to select equal sized subarrays such
// that they have atleast K common elements
int numberOfWays(int a[], int b[], int n,
                            int m, int k)
{
 
    // Combining the two arrays
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i - 1] == b[j - 1])
                prefix_2D[i][j] = 1;
 
            else
                prefix_2D[i][j] = 0;
        }
    }
 
    // Calculating the 2D prefix sum
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            prefix_2D[i][j] += prefix_2D[i][j - 1];
        }
    }
 
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            prefix_2D[i][j] += prefix_2D[i - 1][j];
        }
    }
 
    int answer = 0;
 
    // iterating through all
    // the elements of matrix
    // and considering them to
    // be the bottom right
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
             
            // applying binary search
            // over side length
            int low = 1;
            int high = min(i, j);
 
            while (low < high) {
                int mid = (low + high) >> 1;
 
                // if sum of this submatrix >=k then
                // new search space will be [low, mid]
                if (subMatrixSum(i, j, mid) >= k) {
                    high = mid;
                }
                // else new search space
                // will be [mid+1, high]
                else {
                    low = mid + 1;
                }
            }
 
            // Adding the total submatrices
            if (subMatrixSum(i, j, low) >= k) {
                answer += (min(i, j) - low + 1);
            }
        }
    }
    return answer;
}
 
// Driver Code
int main()
{
    int N = 2, M = 3;
    int A[N] = { 1, 2 };
    int B[M] = { 1, 2, 3 };
 
    int K = 1;
 
    cout << numberOfWays(A, B, N, M, K);
    return 0;
}


Java
// Java implementation to count the
// number of ways to select equal
// sized subarrays such that they
// have atleast K common elements
class GFG{
 
// 2D prefix sum for submatrix
// sum query for matrix
static int [][]prefix_2D = new int[2005][2005];
 
// Function to find the prefix sum
// of the matrix from i and j
static int subMatrixSum(int i, int j, int len)
{
    return prefix_2D[i][j] -
           prefix_2D[i][j - len] -
           prefix_2D[i - len][j] +
           prefix_2D[i - len][j - len];
}
 
// Function to count the number of ways
// to select equal sized subarrays such
// that they have atleast K common elements
static int numberOfWays(int a[], int b[], int n,
                        int m, int k)
{
     
    // Combining the two arrays
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
          if (a[i - 1] == b[j - 1])
              prefix_2D[i][j] = 1;
          else
              prefix_2D[i][j] = 0;
       }
    }
 
    // Calculating the 2D prefix sum
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
          prefix_2D[i][j] += prefix_2D[i][j - 1];
       }
    }
 
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
          prefix_2D[i][j] += prefix_2D[i - 1][j];
       }
    }
 
    int answer = 0;
 
    // Iterating through all
    // the elements of matrix
    // and considering them to
    // be the bottom right
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
           
          // Applying binary search
          // over side length
          int low = 1;
          int high = Math.min(i, j);
           
          while (low < high)
          {
              int mid = (low + high) >> 1;
               
              // If sum of this submatrix >=k then
              // new search space will be [low, mid]
              if (subMatrixSum(i, j, mid) >= k)
              {
                  high = mid;
              }
               
              // Else new search space
              // will be [mid+1, high]
              else
              {
                  low = mid + 1;
              }
          }
           
          // Adding the total submatrices
          if (subMatrixSum(i, j, low) >= k)
          {
              answer += (Math.min(i, j) - low + 1);
          }
       }
    }
    return answer;
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 2, M = 3;
    int A[] = { 1, 2 };
    int B[] = { 1, 2, 3 };
 
    int K = 1;
 
    System.out.print(numberOfWays(A, B, N, M, K));
}
}
 
// This code is contributed by Princi Singh


Python3
# Python3 implementation to count the
# number of ways to select equal
# sized subarrays such that they
# have atleast K common element
 
# 2D prefix sum for submatrix
# sum query for matrix
prefix_2D = [[0 for x in range (2005)]
                for y in range (2005)]
 
# Function to find the prefix sum
# of the matrix from i and j
def subMatrixSum(i, j, length):
 
    return (prefix_2D[i][j] -
            prefix_2D[i][j - length] -
            prefix_2D[i - length][j] +
            prefix_2D[i - length][j - length])
 
# Function to count the number of ways
# to select equal sized subarrays such
# that they have atleast K common elements
def numberOfWays(a, b, n, m, k):
 
    # Combining the two arrays
    for i in range (1, n + 1):
        for j in range (1, m + 1):
            if (a[i - 1] == b[j - 1]):
                prefix_2D[i][j] = 1
            else:
                prefix_2D[i][j] = 0
       
    # Calculating the 2D prefix sum
    for i in range (1, n + 1):
        for j in range (1, m + 1):
            prefix_2D[i][j] += prefix_2D[i][j - 1]
        
    for i in range (1, n + 1):
        for j in range (1, m + 1):
            prefix_2D[i][j] += prefix_2D[i - 1][j]
    answer = 0
 
    # iterating through all
    # the elements of matrix
    # and considering them to
    # be the bottom right
    for i in range (1, n +1):
        for j in range (1, m + 1):
             
            # applying binary search
            # over side length
            low = 1
            high = min(i, j)
 
            while (low < high):
                mid = (low + high) >> 1
 
                # if sum of this submatrix >=k then
                # new search space will be [low, mid]
                if (subMatrixSum(i, j, mid) >= k):
                    high = mid
                 
                # else new search space
                # will be [mid+1, high]
                else:
                    low = mid + 1
 
            # Adding the total submatrices
            if (subMatrixSum(i, j, low) >= k):
                answer += (min(i, j) - low + 1)
          
    return answer
 
# Driver Code
if __name__ == "__main__":
               
    N = 2
    M = 3
    A = [1, 2]
    B = [1, 2, 3]
    K = 1
    print (numberOfWays(A, B, N, M, K))
 
# This code is contributed by Chitranayal


C#
// C# implementation to count the
// number of ways to select equal
// sized subarrays such that they
// have atleast K common elements
using System;
 
class GFG{
 
// 2D prefix sum for submatrix
// sum query for matrix
static int [,]prefix_2D = new int[2005, 2005];
 
// Function to find the prefix sum
// of the matrix from i and j
static int subMatrixSum(int i, int j, int len)
{
    return prefix_2D[i, j] -
           prefix_2D[i, j - len] -
           prefix_2D[i - len, j] +
           prefix_2D[i - len, j - len];
}
 
// Function to count the number of ways
// to select equal sized subarrays such
// that they have atleast K common elements
static int numberOfWays(int []a, int []b, int n,
                        int m, int k)
{
     
    // Combining the two arrays
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
          if (a[i - 1] == b[j - 1])
              prefix_2D[i, j] = 1;
          else
              prefix_2D[i, j] = 0;
       }
    }
 
    // Calculating the 2D prefix sum
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
          prefix_2D[i, j] += prefix_2D[i, j - 1];
            
       }
    }
 
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
          prefix_2D[i, j] += prefix_2D[i - 1, j];
       }
    }
 
    int answer = 0;
 
    // Iterating through all
    // the elements of matrix
    // and considering them to
    // be the bottom right
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= m; j++)
       {
            
          // Applying binary search
          // over side length
          int low = 1;
          int high = Math.Min(i, j);
          while (low < high)
          {
              int mid = (low + high) >> 1;
               
              // If sum of this submatrix >=k then
              // new search space will be [low, mid]
              if (subMatrixSum(i, j, mid) >= k)
              {
                  high = mid;
              }
               
              // Else new search space
              // will be [mid+1, high]
              else
              {
                  low = mid + 1;
              }
          }
           
          // Adding the total submatrices
          if (subMatrixSum(i, j, low) >= k)
          {
              answer += (Math.Min(i, j) - low + 1);
          }
       }
    }
    return answer;
}
 
// Driver Code
public static void Main(String[] args)
{
    int N = 2, M = 3;
    int []A = { 1, 2 };
    int []B = { 1, 2, 3 };
 
    int K = 1;
 
    Console.Write(numberOfWays(A, B, N, M, K));
}
}
 
// This code is contributed by Princi Singh


Javascript


输出:
4

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

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