Convert many to many mappings to maximum no of one to one mappings
Given an array arr1 containing integers from 1..N and another array arr2 containing integers from 1..M. Each element of arr1 is mapped to more than one element in arr2. The task is to maximize the number of one to one mappings possible between both arrays. Here one to one mappings means a unique element of arr1 must be mapped to unique element of arr2. Mapping is given in the form of vector of pairs V where V.first() denotes elements of arr1 and V.second() denotes elements of arr2. Examples:
Input: N = 3, M = 3 arr1[] = {1, 2, 3} arr2[] = {1, 2, 3} V = { {1, 1}, {2, 1}, {2, 2}, {3, 1}, {3, 2}, {3, 3} } Output: 3 Explanation: If we carefully see here mappings are 1 --------> {1} 2 --------> {1, 2} 3 --------> {1, 2, 3} so, maximum number of unique pairings can be done as 1 --------> {1} 2 --------> {2} 3 --------> {3} Input: N = 3, M = 1 V = { {1, 1}, {2, 1}, {3, 1} }; Output: 1 Explanation: Either 1 can be mapped or 2 or 3. so maximum one mapping is possible.
Approach: The approach used here is Greedy. Preprocessing step We are given a vector of pairs which contains mapping information in an unsorted way for eg-
so, we convert this mapping information into a vector of sets mapping. For eg
This is representing the information in one to many mapping form. This can be easily understood by the below diagram
- Find the element in arr1[] which has least number of mappings with elements of arr2[].
- Map this element to first element of its corresponding set.
- Delete all the mappings of this element.
- Also delete all the mappings which contain element from arr2[] those are already mapped.
- Repeat these four steps for all the elements of arr1[].
Below is the implementation of Above approach:
CPP
// C++ Program to convert many to many mapping // to maximum no of one to one mappings #include <bits/stdc++.h> using namespace std; // Returns the maximum number // of one to one mappings between two arrays int FindMax(vector<pair< int , int > >& V, int N, int M) { int ans = 0; // Stores whether an element // from the first array is used in mapping bool * is_paired = new bool [N]; // Contains mapping in sorted form vector<set< int > > mapping(N + 1); // Initialize all the elements // of first array unused memset (is_paired, sizeof (is_paired), false ); // Insert mappings in sorted form for ( int i = 0; i < V.size(); i++) { mapping[V[i].first].insert(V[i].second); } // While there is always at least one element // which can be mapped to a unique element while ( true ) { int lowest = -1; // Finds element to be mapped for ( int i = 1; i <= N; i++) { // There is mapping possible if (mapping[i].size() > 0) { if (lowest == -1) lowest = i; else if (mapping[i].size() < mapping[lowest].size()) lowest = i; } } if (lowest == -1) break ; // Element used in the mapping is_paired[lowest] = true ; int remove = *mapping[lowest].begin(); // Delete all the mappings of used element for ( int i = 1; i <= N; i++) { mapping[i].erase( remove ); if (i == lowest) { mapping[i].clear(); } } ans++; } return ans; } // Main Function int main() { int N = 3; int M = 3; int arr1[] = { 1, 2, 3 }; int arr2[] = { 1, 2, 3 }; vector<pair< int , int > > V{ { 1, 1 }, { 2, 1 }, { 2, 2 }, { 3, 1 }, { 3, 2 }, { 3, 3 } }; cout << FindMax(V, N, M) << endl; return 0; } |
Java
import java.util.*; import java.util.stream.*; // Tuple class definition class Tuple<T1, T2> { // Data members public final T1 Item1; public final T2 Item2; // Constructor public Tuple(T1 item1, T2 item2) { this .Item1 = item1; this .Item2 = item2; } } class GFG { static int findMax(List<Tuple<Integer, Integer> > V, int N, int M) { int ans = 0 ; // Stores whether an element // from the first array is used in mapping boolean [] is_paired = new boolean [N]; // Contains mapping in sorted form List<HashSet<Integer> > mapping = new ArrayList<>(); for ( int i = 0 ; i <= N; i++) { mapping.add( new HashSet<Integer>()); } // Insert mappings in sorted form for (Tuple<Integer, Integer> tuple : V) { mapping.get(tuple.Item1).add(tuple.Item2); } // While there is always at least one element // which can be mapped to a unique element while ( true ) { int lowest = - 1 ; // Finds element to be mapped for ( int i = 1 ; i <= N; i++) { // There is mapping possible if (mapping.get(i).size() > 0 ) { if (lowest == - 1 ) { lowest = i; } else if (mapping.get(i).size() < mapping.get(lowest).size()) { lowest = i; } } } if (lowest == - 1 ) { break ; } // Element used in the mapping is_paired[lowest - 1 ] = true ; int remove = Collections.max(mapping.get(lowest)); mapping.get(lowest).remove(remove); // Delete all the mappings of used element for ( int i = 1 ; i <= N; i++) { mapping.get(i).remove(remove); if (i == lowest) { mapping.get(i).clear(); } } ans++; } return ans; } // Driver code public static void main(String[] args) { int N = 3 ; int M = 3 ; int [] arr1 = new int [] { 1 , 2 , 3 }; int [] arr2 = new int [] { 1 , 2 , 3 }; List<Tuple<Integer, Integer> > V = Arrays.asList( new Tuple<>( 1 , 1 ), new Tuple<>( 2 , 1 ), new Tuple<>( 2 , 2 ), new Tuple<>( 3 , 1 ), new Tuple<>( 3 , 2 ), new Tuple<>( 3 , 3 )); // Function call System.out.println(findMax(V, N, M)); } } |
Python3
# Python3 Program to convert many to many mapping # to maximum no of one to one mappings # Returns the maximum number # of one to one mappings between two arrays def FindMax(V, N, M): ans = 0 # Stores whether an element # from the first array is used in mapping is_paired = [ False ] * N # Contains mapping in sorted form mapping = [ set () for i in range (N + 1 )] # Insert mappings in sorted form for i in range ( len (V)): mapping[V[i][ 0 ]].add(V[i][ 1 ]) # While there is always at least one element # which can be mapped to a unique element while True : lowest = - 1 # Finds element to be mapped for i in range ( 1 , N + 1 ): # There is mapping possible if len (mapping[i]) > 0 : if lowest = = - 1 : lowest = i elif len (mapping[i]) < len (mapping[lowest]): lowest = i if lowest = = - 1 : break # Element used in the mapping is_paired[lowest - 1 ] = True remove = mapping[lowest].pop() # Delete all the mappings of used element for i in range ( 1 , N + 1 ): mapping[i].discard(remove) if i = = lowest: mapping[i].clear() ans + = 1 return ans # Driver code N = 3 M = 3 arr1 = [ 1 , 2 , 3 ] arr2 = [ 1 , 2 , 3 ] V = [( 1 , 1 ), ( 2 , 1 ), ( 2 , 2 ), ( 3 , 1 ), ( 3 , 2 ), ( 3 , 3 )] print (FindMax(V, N, M)) |
C#
using System; using System.Linq; using System.Collections.Generic; class GFG { static int FindMax(List<Tuple< int , int >> V, int N, int M) { int ans = 0; // Stores whether an element // from the first array is used in mapping bool [] is_paired = new bool [N]; // Contains mapping in sorted form List<HashSet< int >> mapping = new List<HashSet< int >>(); for ( int i = 0; i <= N; i++) { mapping.Add( new HashSet< int >()); } // Insert mappings in sorted form foreach ( var tuple in V) { mapping[tuple.Item1].Add(tuple.Item2); } // While there is always at least one element // which can be mapped to a unique element while ( true ) { int lowest = -1; // Finds element to be mapped for ( int i = 1; i <= N; i++) { // There is mapping possible if (mapping[i].Count > 0) { if (lowest == -1) { lowest = i; } else if (mapping[i].Count < mapping[lowest].Count) { lowest = i; } } } if (lowest == -1) { break ; } // Element used in the mapping is_paired[lowest - 1] = true ; int remove = mapping[lowest].Last(); mapping[lowest].Remove(remove); // Delete all the mappings of used element for ( int i = 1; i <= N; i++) { mapping[i].Remove(remove); if (i == lowest) { mapping[i].Clear(); } } ans++; } return ans; } // Driver code static void Main( string [] args) { int N = 3; int M = 3; int [] arr1 = new int [] { 1, 2, 3 }; int [] arr2 = new int [] { 1, 2, 3 }; List<Tuple< int , int >> V = new List<Tuple< int , int >>() { Tuple.Create(1, 1), Tuple.Create(2, 1), Tuple.Create(2, 2), Tuple.Create(3, 1), Tuple.Create(3, 2), Tuple.Create(3, 3), }; // Function call Console.WriteLine(FindMax(V, N, M)); } } |
Javascript
// JavaScript program to convert many to many mapping // to maximum no of one to one mappings // Returns the maximum number of one to one mappings between two arrays function FindMax(V, N, M) { let ans = 0; // Stores whether an element // from the first array is used in mapping let is_paired = new Array(N).fill( false ); // Contains mapping in sorted form let mapping = new Array(N + 1).fill(0).map(() => new Set()); // Insert mappings in sorted form for (let i = 0; i < V.length; i++) { mapping[V[i][0]].add(V[i][1]); } // While there is always at least one element // which can be mapped to a unique element while ( true ) { let lowest = -1; // Finds element to be mapped for (let i = 1; i < N + 1; i++) { // There is mapping possible if (mapping[i].size > 0) { if (lowest === -1) { lowest = i; } else if (mapping[i].size < mapping[lowest].size) { lowest = i; } } } if (lowest === -1) { break ; } // Element used in the mapping is_paired[lowest - 1] = true ; let remove = mapping[lowest].values().next().value; mapping[lowest]. delete (remove); // Delete all the mappings of used element for (let i = 1; i < N + 1; i++) { mapping[i]. delete (remove); if (i === lowest) { mapping[i].clear(); } } ans++; } return ans; } // Driver code let N = 3; let M = 3; let arr1 = [1, 2, 3]; let arr2 = [1, 2, 3]; let V = [[1, 1], [2, 1], [2, 2], [3, 1], [3, 2], [3, 3]]; console.log(FindMax(V, N, M)); |
3
Time Complexity: O(N * x) , as we are using nested loops for traversing N*x times. Where x is maximum no one to one mappings and N is the number of elements in the array.
Auxiliary Space: O(N), as we are using extra space for the map. Where N is the number of elements in the array.
Please Login to comment...