给定一个包含1..N整数的数组 arr1和另一个包含 1..M整数的数组 arr2 。 arr1 的每个元素都映射到arr2 中的多个元素。任务是最大化两个数组之间可能的一对一映射的数量。
这里一对一映射意味着arr1的唯一元素必须映射到arr2 的唯一元素。
映射以 V对向量的形式给出,其中V.first()表示 arr1 的元素, V.second()表示arr2 的元素。
例子:
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.
方法:这里使用的方法是贪婪。
预处理步骤
我们得到一个对向量,其中包含以未排序方式的映射信息,例如-
因此,我们将此映射信息转换为集合映射的向量。
例如:
这是以一对多的映射形式表示信息。
这可以通过下图很容易理解
步骤:
- 找到 arr1[] 中与 arr2[] 元素映射次数最少的元素。
- 将此元素映射到其对应集合的第一个元素。
- 删除此元素的所有映射。
- 还要删除所有包含来自 arr2[] 元素的映射,这些映射已经被映射。
- 对 arr1[] 的所有元素重复这四个步骤。
下面是上述方法的实现:
// C++ Program to convert many to many mapping
// to maximum no of one to one mappings
#include
using namespace std;
// Returns the maximum number
// of one to one mappings between two arrays
int FindMax(vector >& 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 > 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 >
V{ { 1, 1 }, { 2, 1 }, { 2, 2 }, { 3, 1 }, { 3, 2 }, { 3, 3 } };
cout << FindMax(V, N, M) << endl;
return 0;
}
输出:
3
时间复杂度: 其中 x 是最大没有一对一的映射。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。