给定两个数组arr1 []和arr2 [] 。我们可以通过将数组arr1 []的每个元素添加到每个元素arr2 []来生成另一个数组arr3 [] 。任务是在数组arr3 []中找到不同元素的计数。
例子:
Input: Arr1[] = {1, 2}, Arr2[] = {3, 4}, MAX = 4
Output:
4 -> 1
5 -> 2
6 -> 1
Explanation:
Here the third array will be Arr3[] = {1+3, 1+4, 2+3, 2+4} = {4, 5, 5, 6}
Input: Arr1[] = {1, 2}, Arr2[] = {1, 2, 1}, MAX = 2
Output:
2 -> 2
3 -> 3
4 -> 1
Explanation:
Here the third array is Arr3[] = {1+1, 1+2, 1+1, 2+1, 2+2, 2+1} = {2, 3, 2, 3, 4, 3}
Therfore Count of elements from 1 to 2*2 (4) are {0, 2, 3, 1}
天真的方法:天真的方法是从给定的两个数组中找到所有可能的对的和,并将该和插入到数组arr3 []中。打印数组arr3 []的所有元素的频率。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find Occurence of each
// element from 1 to 2*MAX
void findCount(vector& Arr1,
vector& Arr2)
{
// Intialise MAX
int MAX = max(*max_element(Arr1.begin(),
Arr1.end()),
*max_element(Arr2.begin(),
Arr2.end()));
// Count vector to store count of
// each element from 1 to 2*MAX
vector Count(2 * MAX + 1, 0);
// Size of Arr1 and Arr2
int n = Arr1.size(), m = Arr2.size();
// Find the elements of arr3[] and
// increase count of element by 1
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int element = Arr1[i] + Arr2[j];
Count[element]++;
}
}
// Print the result
for (int i = 1; i <= 2 * MAX; i++) {
if (Count[i] > 0) {
cout << i << "->"
<< Count[i] << endl;
}
}
}
// Driver Code
int main()
{
// Given arrays arr1[] and arr2[]
vector arr1 = { 1, 2 };
vector arr2 = { 1, 2, 1 };
// Function Call
findCount(arr1, arr2);
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
// Function to find Occurence of each
// element from 1 to 2*MAX
static void findCount(int[] Arr1, int[]Arr2)
{
// Initialise MAX
int MAX = Math.max(Arrays.stream(Arr1).max().getAsInt(),
Arrays.stream(Arr2).max().getAsInt());
// Count vector to store count of
// each element from 1 to 2*MAX
int[] Count = new int[2 * MAX + 1];
// Size of Arr1 and Arr2
int n = Arr1.length, m = Arr2.length;
// Find the elements of arr3[] and
// increase count of element by 1
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
int element = Arr1[i] + Arr2[j];
Count[element]++;
}
}
// Print the result
for(int i = 1; i <= 2 * MAX; i++)
{
if (Count[i] > 0)
{
System.out.print(i + "->" +
Count[i] + "\n");
}
}
}
// Driver Code
public static void main(String[] args)
{
// Given arrays arr1[] and arr2[]
int[] arr1 = { 1, 2 };
int[] arr2 = { 1, 2, 1 };
// Function call
findCount(arr1, arr2);
}
}
// This code is contributed by sapnasingh4991
Python3
# Python3 program for the above approach
# Function to find Occurence of each
# element from 1 to 2*MAX
def findCount(Arr1, Arr2):
# Initialise MAX
MAX = max(max(Arr1), max(Arr2));
# Count vector to store count of
# each element from 1 to 2*MAX
#Count = new int[2 * MAX + 1];
Count = [0 for i in range(2 * MAX + 1)]
# Size of Arr1 and Arr2
n = len(Arr1);
m = len(Arr2);
# Find the elements of arr3 and
# increase count of element by 1
for i in range(n):
for j in range(m):
element = Arr1[i] + Arr2[j];
Count[element]+=1;
# Prthe result
for i in range(1,2*MAX+1):
if (Count[i] > 0):
print(i , "->" , Count[i]);
# Driver Code
if __name__ == '__main__':
# Given arrays arr1 and arr2
arr1 = [1, 2 ];
arr2 = [ 1, 2, 1 ];
# Function call
findCount(arr1, arr2);
# This code is contributed by Rohit_ranjan
C#
// C# program for the above approach
using System;
using System.Linq;
class GFG{
// Function to find Occurence of each
// element from 1 to 2*MAX
static void findCount(int[] Arr1, int[]Arr2)
{
// Initialise MAX
int MAX = Math.Max(Arr1.Max(), Arr2.Max());
// Count vector to store count of
// each element from 1 to 2*MAX
int[] Count = new int[2 * MAX + 1];
// Size of Arr1 and Arr2
int n = Arr1.Length, m = Arr2.Length;
// Find the elements of arr3[] and
// increase count of element by 1
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
int element = Arr1[i] + Arr2[j];
Count[element]++;
}
}
// Print the result
for(int i = 1; i <= 2 * MAX; i++)
{
if (Count[i] > 0)
{
Console.Write(i + "->" +
Count[i] + "\n");
}
}
}
// Driver Code
public static void Main(String[] args)
{
// Given arrays arr1[] and arr2[]
int[] arr1 = { 1, 2 };
int[] arr2 = { 1, 2, 1 };
// Function call
findCount(arr1, arr2);
}
}
// This code is contributed by Princi Singh
C++
// C++ program for the above approach
#include
using namespace std;
using cd = complex;
// Value of PI need in FFT
const double PI = acos(-1);
// Function to implement the FFT
void fft(vector& a, bool invert)
{
int n = a.size();
if (n == 1)
return;
vector a0(n / 2), a1(n / 2);
for (int i = 0; 2 * i < n; i++) {
a0[i] = a[2 * i];
a1[i] = a[2 * i + 1];
}
// Recursively find fft
fft(a0, invert);
fft(a1, invert);
double ang = 2 * PI / n * (invert ? -1 : 1);
cd w(1), wn(cos(ang), sin(ang));
for (int i = 0; 2 * i < n; i++) {
a[i] = a0[i] + w * a1[i];
a[i + n / 2] = a0[i] - w * a1[i];
if (invert) {
a[i] /= 2;
a[i + n / 2] /= 2;
}
w *= wn;
}
}
// Function to multiply two polynomials
// A(x) and B(x) using FFT
vector multiply(vector const& a,
vector const& b)
{
vector fa(a.begin(), a.end()),
fb(b.begin(), b.end());
int n = 1;
while (n < a.size() + b.size()) {
n <<= 1;
}
// Resize fa and fb
fa.resize(n);
fb.resize(n);
// Assign initially false
fft(fa, false);
fft(fb, false);
for (int i = 0; i < n; i++)
fa[i] *= fb[i];
fft(fa, true);
// To store the result
vector result(n);
for (int i = 0; i < n; i++)
result[i] = round(fa[i].real());
// Return result
return result;
}
// Function to find the Count of each
// element from 1 to 2*MAX
void findCount(vector& Arr1,
vector& Arr2)
{
// Intialise MAX
int MAX = max(*max_element(Arr1.begin(),
Arr1.end()),
*max_element(Arr2.begin(),
Arr2.end()));
int n = Arr1.size();
int m = Arr2.size();
// vector for Polynomial A(x) from Arr1
vector A(MAX + 1);
for (int i = 0; i < n; i++) {
A[Arr1[i]]++;
}
// Vector for Polynomial B(x) from Arr2
vector B(MAX + 1);
for (int i = 0; i < m; i++) {
B[Arr2[i]]++;
}
// Vector to store the result of
// multiplication of A(x) and B(x)
vector P;
// Multiplying Arr1 and Arr2 and
// storing in P is same as Count
P = multiply(A, B);
// Print the result
for (int i = 1; i <= 2 * MAX; i++) {
if (P[i] > 0) {
cout << i << "->"
<< P[i] << endl;
}
}
cout << '\n';
}
// Driver Code
int main()
{
// Given arrays arr1[] and arr2[]
vector arr1 = { 1, 2 };
vector arr2 = { 1, 2, 1 };
// Function Call
findCount(arr1, arr2);
}
2->2
3->3
4->1
时间复杂度: O(N 2 )
空间复杂度: O(N)
高效的解决方案:可以借助FFT(快速傅立叶变换)有效地完成给定的任务。步骤如下:
- 考虑示例Arr1 [] = {1,2}和Arr2 [] = {1,2,1} 。令Count为频率阵列,即Count [i]代表结果阵列中i的频率。
- 当Arr1 [i]添加到Arr2 [j]时,我们增加Count [s],其中s = Arr1 [i] + Arr2 [j]。这类似于将多项式相乘得到的幂。
- 令A(x)为Arr1 []表示的多项式。 Arr1的元素表示x的幂,并且Arr1中的元素的计数是多项式中具有该幂的系数项。
So,
Similiarily
Let
- 对于每个项,x的幂代表结果元素,系数代表其计数。
- 如果条件是
- 然后Count [i] = k。此处Count与P(x)相同。
- 要计算P(x)的值,我们可以简单地将A(x)和B(x)相乘。
多项式乘法的朴素方法取O(N 2 )。为了使乘法更快,我们可以使用FFT(快速傅立叶变换)。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
using cd = complex;
// Value of PI need in FFT
const double PI = acos(-1);
// Function to implement the FFT
void fft(vector& a, bool invert)
{
int n = a.size();
if (n == 1)
return;
vector a0(n / 2), a1(n / 2);
for (int i = 0; 2 * i < n; i++) {
a0[i] = a[2 * i];
a1[i] = a[2 * i + 1];
}
// Recursively find fft
fft(a0, invert);
fft(a1, invert);
double ang = 2 * PI / n * (invert ? -1 : 1);
cd w(1), wn(cos(ang), sin(ang));
for (int i = 0; 2 * i < n; i++) {
a[i] = a0[i] + w * a1[i];
a[i + n / 2] = a0[i] - w * a1[i];
if (invert) {
a[i] /= 2;
a[i + n / 2] /= 2;
}
w *= wn;
}
}
// Function to multiply two polynomials
// A(x) and B(x) using FFT
vector multiply(vector const& a,
vector const& b)
{
vector fa(a.begin(), a.end()),
fb(b.begin(), b.end());
int n = 1;
while (n < a.size() + b.size()) {
n <<= 1;
}
// Resize fa and fb
fa.resize(n);
fb.resize(n);
// Assign initially false
fft(fa, false);
fft(fb, false);
for (int i = 0; i < n; i++)
fa[i] *= fb[i];
fft(fa, true);
// To store the result
vector result(n);
for (int i = 0; i < n; i++)
result[i] = round(fa[i].real());
// Return result
return result;
}
// Function to find the Count of each
// element from 1 to 2*MAX
void findCount(vector& Arr1,
vector& Arr2)
{
// Intialise MAX
int MAX = max(*max_element(Arr1.begin(),
Arr1.end()),
*max_element(Arr2.begin(),
Arr2.end()));
int n = Arr1.size();
int m = Arr2.size();
// vector for Polynomial A(x) from Arr1
vector A(MAX + 1);
for (int i = 0; i < n; i++) {
A[Arr1[i]]++;
}
// Vector for Polynomial B(x) from Arr2
vector B(MAX + 1);
for (int i = 0; i < m; i++) {
B[Arr2[i]]++;
}
// Vector to store the result of
// multiplication of A(x) and B(x)
vector P;
// Multiplying Arr1 and Arr2 and
// storing in P is same as Count
P = multiply(A, B);
// Print the result
for (int i = 1; i <= 2 * MAX; i++) {
if (P[i] > 0) {
cout << i << "->"
<< P[i] << endl;
}
}
cout << '\n';
}
// Driver Code
int main()
{
// Given arrays arr1[] and arr2[]
vector arr1 = { 1, 2 };
vector arr2 = { 1, 2, 1 };
// Function Call
findCount(arr1, arr2);
}
2->2
3->3
4->1
时间复杂度: O(N * log N)
辅助空间: O(N)