Count distinct elements after adding each element of First Array with Second Array
Given two arrays arr1[] and arr2[]. We can generate another array arr3[] by adding each element of the array arr1[] to each element arr2[]. The task is to find the count of distinct element in the array arr3[].
Examples:
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}
Therefore Count of elements from 1 to 2*2 (4) are {0, 2, 3, 1}
Naive Approach: The naive approach is to find the sum of all possible pairs from the given two arrays and insert that sum into the array arr3[]. Print the frequency of all the elements of the array arr3[].
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; // Function to find Occurrence of each // element from 1 to 2*MAX void findCount(vector< int >& Arr1, vector< int >& Arr2) { // Initialise 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< int > 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< int > arr1 = { 1, 2 }; vector< int > arr2 = { 1, 2, 1 }; // Function Call findCount(arr1, arr2); } |
Java
// Java program for the above approach import java.util.*; class GFG{ // Function to find Occurrence 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 Occurrence 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 ; # Print the 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 Occurrence 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 |
Javascript
<script> // JavaScript program for the above approach // Function to find Occurrence of each // element from 1 to 2*MAX function findCount(Arr1, Arr2) { // Initialise MAX let MAX = Math.max(Math.max(...Arr1), Math.max(...Arr2)); // Count vector to store count of // each element from 1 to 2*MAX let Count = Array.from({length: 2 * MAX + 1}, (_, i) => 0); // Size of Arr1 and Arr2 let n = Arr1.length, m = Arr2.length; // Find the elements of arr3[] and // increase count of element by 1 for (let i = 0; i < n; i++) { for (let j = 0; j < m; j++) { let element = Arr1[i] + Arr2[j]; Count[element]++; } } // Print the result for (let i = 1; i <= 2 * MAX; i++) { if (Count[i] > 0) { document.write(i + "->" + Count[i] + "<br/>" ); } } } // Driver Code // Given arrays arr1[] and arr2[] let arr1 = [ 1, 2 ]; let arr2 = [ 1, 2, 1 ]; // Function call findCount(arr1, arr2); </script> |
2->2 3->3 4->1
Time Complexity: O(N2)
Space Complexity: O(N)
Efficient Solution: The given task can be efficiently done with the help of FFT(Fast Fourier Transform). Below are the steps:
- Consider the examples Arr1[] = {1, 2} and Arr2[] = {1, 2, 1}. Let Count be the frequency array i.e., Count[i] represents the frequency of i in resultant array.
- When Arr1[i] is added to Arr2[j], we increment Count[s] where s = Arr1[i]+Arr2[j]. This is similar to multiplying polynomials as there power get added.
- Let A(x) be the polynomial represented by Arr1[]. Elements of Arr1 represents power of x and their count in Arr1 are coefficients terms with that power in polynomial.
- For each term, power of x represents the resulting element and the coefficient represents its count.
- If term is
- Then Count[i] = k. Here Count is same as P(x).
- To calculate the value of P(x), we can simply multiply A(x) and B(x).
The Naive method of polynomial multiplication takes O(N2). To make the multiplication faster we can use FFT(Fast Fourier Transform).
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; using cd = complex< double >; // Value of PI need in FFT const double PI = acos (-1); // Function to implement the FFT void fft(vector<cd>& a, bool invert) { int n = a.size(); if (n == 1) return ; vector<cd> 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< int > multiply(vector< int > const & a, vector< int > const & b) { vector<cd> 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< int > 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< int >& Arr1, vector< int >& Arr2) { // Initialise 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< int > A(MAX + 1); for ( int i = 0; i < n; i++) { A[Arr1[i]]++; } // Vector for Polynomial B(x) from Arr2 vector< int > 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< int > 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< int > arr1 = { 1, 2 }; vector< int > arr2 = { 1, 2, 1 }; // Function Call findCount(arr1, arr2); } |
Java
import java.util.*; // Complex class definition class Complex { // Data members public double real, imag; // Constructor public Complex( double real, double imag) { this .real = real; this .imag = imag; } // Method to add two Complex objects public Complex add(Complex other) { return new Complex(real + other.real, imag + other.imag); } // Method to subtract two Complex objects public Complex subtract(Complex other) { return new Complex(real - other.real, imag - other.imag); } // Method to multiply two Complex objects public Complex multiply(Complex other) { double re = real * other.real - imag * other.imag; double im = real * other.imag + imag * other.real; return new Complex(re, im); } // Method to divide two Complex objects public Complex divide(Complex other) { double denom = other.real * other.real + other.imag * other.imag; double re = (real * other.real + imag * other.imag) / denom; double im = (imag * other.real - real * other.imag) / denom; return new Complex(re, im); } } class GFG { // Function to implement the FFT public static void fft(ArrayList<Complex> a, boolean invert) { int n = a.size(); if (n == 1 ) { return ; } ArrayList<Complex> a0 = new ArrayList<>(); ArrayList<Complex> a1 = new ArrayList<>(); for ( int i = 0 ; 2 * i < n; i++) { a0.add(a.get( 2 * i)); a1.add(a.get( 2 * i + 1 )); } // Recursively find fft fft(a0, invert); fft(a1, invert); double ang = 2 * Math.PI / n * (invert ? - 1 : 1 ); Complex w = new Complex( 1 , 0 ); Complex wn = new Complex(Math.cos(ang), Math.sin(ang)); for ( int i = 0 ; 2 * i < n; i++) { a.set(i, a0.get(i).add(w.multiply(a1.get(i)))); a.set(i + n / 2 , a0.get(i).subtract( w.multiply(a1.get(i)))); if (invert) { a.set(i, a.get(i).divide( new Complex( 2 , 0 ))); a.set(i + n / 2 , a.get(i + n / 2 ).divide( new Complex( 2 , 0 ))); } w = w.multiply(wn); } } // Function to multiply two polynomials // A(x) and B(x) using FFT public static ArrayList<Integer> multiply( int [] a, int [] b) { ArrayList<Complex> fa = new ArrayList<>(); ArrayList<Complex> fb = new ArrayList<>(); for ( int i = 0 ; i < a.length; i++) { fa.add( new Complex(a[i], 0 )); } for ( int i = 0 ; i < b.length; i++) { fb.add( new Complex(b[i], 0 )); } int n = 1 ; while (n < a.length + b.length) { n <<= 1 ; } // Resize fa and fb while (fa.size() < n) { fa.add( new Complex( 0 , 0 )); } while (fb.size() < n) { fb.add( new Complex( 0 , 0 )); } // Assign initially false fft(fa, false ); fft(fb, false ); for ( int i = 0 ; i < n; i++) { fa.set(i, fa.get(i).multiply(fb.get(i))); } fft(fa, true ); // To store the result ArrayList<Integer> result = new ArrayList<>(); for ( int i = 0 ; i < n; i++) { result.add(( int )Math.round(fa.get(i).real)); } // Return result return result; } // Function to find the Count of each // element from 1 to 2*MAX public static void findCount(ArrayList<Integer> arr1, ArrayList<Integer> arr2) { // Initialise MAX int MAX = Math.max(Collections.max(arr1), Collections.max(arr2)); int n = arr1.size(); int m = arr2.size(); // vector for Polynomial A(x) from Arr1 int [] A = new int [MAX + 1 ]; for ( int i = 0 ; i < n; i++) { A[arr1.get(i)]++; } // Vector for Polynomial B(x) from Arr2 int [] B = new int [MAX + 1 ]; for ( int i = 0 ; i < m; i++) { B[arr2.get(i)]++; } // Vector to store the result of // multiplication of A(x) and B(x) ArrayList<Integer> P = multiply(A, B); // Print the result for ( int i = 1 ; i <= 2 * MAX; i++) { if (P.get(i) > 0 ) { System.out.println(i + "->" + P.get(i)); } } System.out.println(); } // Driver Code public static void main(String[] args) { // Given arrays arr1[] and arr2[] ArrayList<Integer> arr1 = new ArrayList<Integer>(); arr1.add( 1 ); arr1.add( 2 ); ArrayList<Integer> arr2 = new ArrayList<Integer>(); arr2.add( 1 ); arr2.add( 2 ); arr2.add( 1 ); // Function Call findCount(arr1, arr2); } } |
Python3
import math # Python3 program to implement the above approach # Value of PI need in FFT PI = math.acos( - 1 ) # Function to implement the FFT def fft(a, invert): n = len (a) if (n = = 1 ): return a0 = [ 0 ] * (n / / 2 ) a1 = [ 0 ] * (n / / 2 ) for i in range (n / / 2 ): a0[i] = a[ 2 * i] a1[i] = a[ 2 * i + 1 ] # Recursively find fft fft(a0, invert) fft(a1, invert) ang = 2 * PI / n * ( - 1 if invert else 1 ) w = complex ( 1 ) wn = complex (math.cos(ang), math.sin(ang)) for i in range (n / / 2 ): 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 def multiply(a, b): fa = [ complex (i, 0 ) for i in a] fb = [ complex (i, 0 ) for i in b] n = 1 while (n < len (a) + len (b)): n << = 1 # Resize fa and fb fa + = [ complex ( 0 )] * (n - len (fa)) fb + = [ complex ( 0 )] * (n - len (fb)) # Assign initially false fft(fa, False ) fft(fb, False ) for i in range (n): fa[i] * = fb[i] fft(fa, True ) # To store the result result = [ 0 ] * n for i in range (n): result[i] = round (fa[i].real) # Return result return result # Function to find the Count of each # element from 1 to 2*MAX def findCount(Arr1, Arr2): # Initialise MAX MAX = max ( max (Arr1), max (Arr2)) n = len (Arr1) m = len (Arr2) # vector for Polynomial A(x) from Arr1 A = [ 0 ] * ( MAX + 1 ) for i in range (n): A[Arr1[i]] + = 1 # Vector for Polynomial B(x) from Arr2 B = [ 0 ] * ( MAX + 1 ) for i in range (m): B[Arr2[i]] + = 1 # Vector to store the result of # multiplication of A(x) and B(x) P = [] # Multiplying Arr1 and Arr2 and # storing in P is same as Count P = multiply(A, B) # Print the result for i in range ( 1 , 2 * MAX + 1 ): if (P[i] > 0 ): print ( str (i) + "->" + str (P[i])) print () # Driver Code if __name__ = = "__main__" : # Given arrays arr1[] and arr2[] arr1 = [ 1 , 2 ] arr2 = [ 1 , 2 , 1 ] # Function Call findCount(arr1, arr2) |
C#
using System; using System.Linq; using System.Collections.Generic; // Complex class definition class Complex { // Data members public double real, imag; // Constructor public Complex( double real, double imag) { this .real = real; this .imag = imag; } // Method to Add two Complex objects public Complex Add(Complex other) { return new Complex(real + other.real, imag + other.imag); } // Method to subtract two Complex objects public Complex Subtract(Complex other) { return new Complex(real - other.real, imag - other.imag); } // Method to multiply two Complex objects public Complex Multiply(Complex other) { double re = real * other.real - imag * other.imag; double im = real * other.imag + imag * other.real; return new Complex(re, im); } // Method to divide two Complex objects public Complex Divide(Complex other) { double denom = other.real * other.real + other.imag * other.imag; double re = (real * other.real + imag * other.imag) / denom; double im = (imag * other.real - real * other.imag) / denom; return new Complex(re, im); } } class GFG { // Function to implement the FFT public static void fft(List<Complex> a, bool invert) { int n = a.Count; if (n == 1) return ; List<Complex> a0 = new List<Complex>(); List<Complex> a1 = new List<Complex>(); for ( int i = 0; 2 * i < n; i++) { a0.Add(a[2 * i]); a1.Add(a[2 * i + 1]); } // Recursively find fft fft(a0, invert); fft(a1, invert); double ang = 2 * Math.PI / n * (invert ? -1 : 1); Complex w = new Complex(1, 0); Complex wn = new Complex(Math.Cos(ang), Math.Sin(ang)); for ( int i = 0; 2 * i < n; i++) { a[i] = a0[i].Add(w.Multiply(a1[i])); a[i + n / 2] = a0[i].Subtract(w.Multiply(a1[i])); if (invert) { a[i] = a[i].Divide( new Complex(2, 0)); a[i + n / 2] = a[i + n / 2].Divide( new Complex(2, 0)); } w = w.Multiply(wn); } } // Function to multiply two polynomials A(x) and B(x) // using FFT public static List< int > Multiply( int [] a, int [] b) { List<Complex> fa = new List<Complex>(); List<Complex> fb = new List<Complex>(); for ( int i = 0; i < a.Length; i++) fa.Add( new Complex(a[i], 0)); for ( int i = 0; i < b.Length; i++) fb.Add( new Complex(b[i], 0)); int n = 1; while (n < a.Length + b.Length) n <<= 1; // Resize fa and fb while (fa.Count < n) fa.Add( new Complex(0, 0)); while (fb.Count < n) fb.Add( new Complex(0, 0)); // Assign initially false fft(fa, false ); fft(fb, false ); for ( int i = 0; i < n; i++) { fa[i] = fa[i].Multiply(fb[i]); } fft(fa, true ); // To store the result List< int > result = new List< int >(); for ( int i = 0; i < n; i++) { result.Add(( int )Math.Floor(fa[i].real)); } // Return result return result; } // Function to find the Count of each // element from 1 to 2*MAX public static void FindCount(List< int > arr1, List< int > arr2) { // Initialise MAX int MAX = Math.Max(arr1.Max(), arr2.Max()); int n = arr1.Count; int m = arr2.Count; // vector for Polynomial A(x) from Arr1 int [] A = new int [MAX + 1]; for ( int i = 0; i < n; i++) { A[arr1[i]]++; } // Vector for Polynomial B(x) from Arr2 int [] B = new int [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) List< int > P = Multiply(A, B); // Print the result for ( int i = 1; i <= 2 * MAX; i++) { if (P[i] > 0) { Console.WriteLine(i + "->" + P[i]); } } Console.WriteLine( " " ); } // Driver Code public static void Main( string [] args) { // Given arrays arr1[] and arr2[] List< int > arr1 = new List< int >(); arr1.Add(1); arr1.Add(2); List< int > arr2 = new List< int >(); arr2.Add(1); arr2.Add(2); arr2.Add(1); // Function Call FindCount(arr1, arr2); } } |
Javascript
// Complex class definition class Complex { // Data members constructor(real, imag) { this .real = real; this .imag = imag; } // Method to add two Complex objects add(other) { return new Complex( this .real + other.real, this .imag + other.imag); } // Method to subtract two Complex objects subtract(other) { return new Complex( this .real - other.real, this .imag - other.imag); } // Method to multiply two Complex objects multiply(other) { let re = this .real * other.real - this .imag * other.imag; let im = this .real * other.imag + this .imag * other.real; return new Complex(re, im); } // Method to divide two Complex objects divide(other) { let denom = other.real * other.real + other.imag * other.imag; let re = ( this .real * other.real + this .imag * other.imag) / denom; let im = ( this .imag * other.real - this .real * other.imag) / denom; return new Complex(re, im); } } // Function to implement the FFT function fft(a, invert) { let n = a.length; if (n == 1) { return ; } let a0 = []; let a1 = []; for (let i = 0; 2 * i < n; i++) { a0.push(a[2 * i]); a1.push(a[2 * i + 1]); } // Recursively find fft fft(a0, invert); fft(a1, invert); let ang = 2 * Math.PI / n * (invert ? -1 : 1); let w = new Complex(1, 0); let wn = new Complex(Math.cos(ang), Math.sin(ang)); for (let i = 0; 2 * i < n; i++) { a[i] = a0[i].add(w.multiply(a1[i])); a[i + n / 2] = a0[i].subtract( w.multiply(a1[i])); if (invert) { a[i] = a[i].divide( new Complex(2, 0)); a[i + n / 2] = a[i + n / 2].divide( new Complex(2, 0)); } w = w.multiply(wn); } } // Function to multiply two polynomials // A(x) and B(x) using FFT function multiply(a, b) { let fa = []; let fb = []; for (let i = 0; i < a.length; i++) { fa.push( new Complex(a[i], 0)); } for (let i = 0; i < b.length; i++) { fb.push( new Complex(b[i], 0)); } let n = 1; while (n < a.length + b.length) { n <<= 1; } // Resize fa and fb while (fa.length < n) { fa.push( new Complex(0, 0)); } while (fb.length < n) { fb.push( new Complex(0, 0)); } // Assign initially false fft(fa, false ); fft(fb, false ); for (let i = 0; i < n; i++) { fa[i] = fa[i].multiply(fb[i]); } fft(fa, true ); // To store the result let result = [] for ( var i = 0; i < n; i++) { result.push(Math.floor(fa[i].real)); } // Return result return result; } // Function to find the Count of each // element from 1 to 2*MAX function findCount(arr1, arr2) { // Initialise MAX let MAX = Math.max(Math.max(...arr1), Math.max(...arr2)); let n = arr1.length; let m = arr2.length; // vector for Polynomial A(x) from Arr1 let A = new Array(MAX + 1).fill(0); for ( var i = 0; i < n; i++) { A[arr1[i]]++; } // Vector for Polynomial B(x) from Arr2 let B = new Array(MAX + 1).fill(0); for ( var i = 0; i < m; i++) { B[arr2[i]]++; } // Vector to store the result of // multiplication of A(x) and B(x) let P = multiply(A, B); // Print the result for ( var i = 1; i <= 2 * MAX; i++) { if (P[i] > 0) { console.log(i + "->" + P[i]); } } console.log( " " ) } // Driver Code // Given arrays arr1[] and arr2[] let arr1 = [] arr1.push(1); arr1.push(2); let arr2 = [] arr2.push(1); arr2.push(2); arr2.push(1); // Function Call findCount(arr1, arr2); |
2->2 3->3 4->1
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Please Login to comment...