给定两个长度为N 的数组A和B ,其中填充了从1到N的自然数排列,任务是计算A和B中公共子数组的数量。
例子:
Input: A = [1, 2, 3], B = [2, 3, 1]
Output: 4
Explanation:
The common subarrays are [1], [2], [3], [2, 3]
Hence, total count = 4
Input: A = [1, 2, 3, 4, 5], B = [2, 3, 1, 4, 5]
Output: 7
Explanation:
The common subarrays are [1], [2], [3], [4], [5], [2, 3], [4, 5]
Hence, total count = 7
天真的方法:
这个想法是分别生成A和B 的所有子数组,每个数组需要O(N 2 ) 。现在,将 A 的所有子数组与 B 的所有子数组进行比较并计算公共子数组。这需要O(N 4 ) 。
有效的方法:
这个想法是使用Hashing来有效地解决这个问题。
- 创建一个大小为N+1的哈希数组H 。
- 用它们各自的索引表示A的所有元素:
Element Representaion
A[0] 0
A[1] 1
A[2] 2
.
.
and so on.
- 使用数组 H 来存储这个表示, H[ A[ i ] ] = i
- 使用 H, B[ i ] = H[ B[ i ] ]根据这个新表示更新B的元素
- 现在,数组 A 可以表示为 [0, 1, 2, ..N],因此只需计算 B 中具有连续元素的子数组的数量。一旦我们得到连续元素子数组的长度K ,使用以下关系计算可能的子数组总数:
Total number of subarrays = (K * (K + 1)) / 2
查看此示例以详细了解此方法:
Example:
A = [4, 3, 1, 2, 5]
B = [3, 1, 2, 4, 5]
Common subarrays are [1], [2], [3], [4], [5], [3, 1], [1, 2], [3, 1, 2] = 8
1. Represent A[i] as i, and store in H as H[A[i]] = i, Now array H from index 1 to N is,
H = [2, 3, 1, 0, 4]
2. Update B according to H, B[i] = H[B[i]]
B = [1, 2, 3, 0, 4]
3. Look for subarray in B with consecutive elements,
Subarray from index 0 to 2 is [1, 2, 3], consisting of consecutive elements with length K = 3
Element at index 3 forms a subarray [0] of length K = 1
Element at index 4 forms a subarray [4] of length K = 1
4. Total number of common subarrays =
(3*(3+1))/2 + (1*(1+1))/2 + (1*(1+1))/2 = 6 + 1 + 1 = 8
下面是上述方法的实现:
C++
// C++ implementation of above approach
#include
using namespace std;
int commonSubarrays(int *A, int *B, int N)
{
// Initialising Map for
// Index Mapping
int Map[N + 1];
// Mapping elements of A
for(int i = 0 ; i< N; i++)
Map[*(A + i)] = i;
// Modify elements of B
// according to Map
for (int i = 0; i < N; i++)
{
// Changing B[i] as
// the index of B[i] in A
*(B + i) = Map[*(B + i)];
}
// Count of common subarrays
int count = 0;
// Traversing array B
int i = 0, K;
while (i < N)
{
K = 1;
i+= 1;
// While consecutive elements
// are found, we increment K
while (i < N && B[i] == B[i - 1] + 1)
{
i += 1;
K += 1;
}
// Add number of subarrays
//with length K
// to total count
count = count + ((K) * (K + 1)) / 2;
}
return count;
}
// Driver code
int main()
{
int N = 3;
int A[] = {1, 2, 3};
int B[] = {2, 3, 1};
cout << (commonSubarrays(A, B, N))
<< endl;
N = 5;
int C[] = {1, 2, 3, 4, 5};
int D[] = {2, 3, 1, 4, 5};
cout << (commonSubarrays(C, D, N));
}
// This code is contributed by chitranayal
Java
// Java implementation of the above approach
class GFG{
static int commonSubarrays(int []A,
int []B, int N)
{
// Initialising Map for
// Index Mapping
int []Map = new int[N + 1];
// Mapping elements of A
for(int i = 0; i< N; i++)
Map[A[i]] = i;
// Modify elements of B
// according to Map
for(int i = 0; i < N; i++)
{
// Changing B[i] as
// the index of B[i] in A
B[i] = Map[B[i]];
}
// Count of common subarrays
int count = 0;
// Traversing array B
int i = 0, K;
while (i < N)
{
K = 1;
i+= 1;
// While consecutive elements
// are found, we increment K
while (i < N && B[i] == B[i - 1] + 1)
{
i += 1;
K += 1;
}
// Add number of subarrays
//with length K
// to total count
count = count + ((K) * (K + 1)) / 2;
}
return count;
}
// Driver code
public static void main(String[] args)
{
int N = 3;
int A[] = {1, 2, 3};
int B[] = {2, 3, 1};
System.out.print(commonSubarrays(A, B, N));
System.out.print("\n");
N = 5;
int C[] = {1, 2, 3, 4, 5};
int D[] = {2, 3, 1, 4, 5};
System.out.print(commonSubarrays(C, D, N));
}
}
// This code is contributed by gauravrajput1
Python3
# Python3 implementation of above approach
def commonSubarrays(A, B, N):
# Initialising Map for
# Index Mapping
Map = [0 for i in range(N + 1)]
# Mapping elements of A
for i in range(N):
Map[A[i]]= i
# Modify elements of B
# according to Map
for i in range(N) :
# Changing B[i] as
# the index of B[i] in A
B[i]= Map[B[i]]
# Count of common subarrays
count = 0
# Traversing array B
i = 0
while i
C#
// C# implementation of the above approach
using System;
class GFG{
static int commonSubarrays(int []A,
int []B,
int N)
{
// Initialising Map for
// Index Mapping
int []Map = new int[N + 1];
// Mapping elements of A
for(int i = 0; i < N; i++)
Map[A[i]] = i;
// Modify elements of B
// according to Map
for(int i = 0; i < N; i++)
{
// Changing B[i] as
// the index of B[i] in A
B[i] = Map[B[i]];
}
// Count of common subarrays
int count = 0;
// Traversing array B
int a = 0, K;
while (a < N)
{
K = 1;
a += 1;
// While consecutive elements
// are found, we increment K
while (a < N && B[a] == B[a - 1] + 1)
{
a += 1;
K += 1;
}
// Add number of subarrays
//with length K
// to total count
count = count + ((K) * (K + 1)) / 2;
}
return count;
}
// Driver code
public static void Main()
{
int N = 3;
int []A = {1, 2, 3};
int []B = {2, 3, 1};
Console.Write(commonSubarrays(A, B, N));
Console.Write("\n");
N = 5;
int []C = {1, 2, 3, 4, 5};
int []D = {2, 3, 1, 4, 5};
Console.Write(commonSubarrays(C, D, N));
}
}
// This code is contributed by Code_Mech
Javascript
4
7
时间复杂度: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live