问题: 快速找到和为零的四个数
时间限制: 2.00s | 内存限制: 128MB
题目描述
定义求和问题如下:给定 4 组整数 A,B,C,D,找到有多少四元组 (a,b,c,d)∈A×B×C×D(a, b, c, d) , 满足条件a+b+c+d=0。此问题中,假设A,B,C,D 具有相同的大小 n。
输入
输入包含多组测试数据。每组测试数据的第一行包含一个整数 n,表示 A,B,C,D 的元素个数(n≤1000)。接下来 n 行每行 4 个整数,分别属于 A,B,C,D,每个整数的大小在 [−228,228]之间。
输出
对于每组测试数据,输出满足条件的四元组的个数。
输入输出样例
样例输入 #1
复制
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
样例输出 #1
复制
5
unorder_map用法:
当我们需要键值对映射起来,并且希望快速的通过键来寻找值时,unorder_map就是一种非常好用的数据结构,在C++标准库当中,unorder_map是一种哈希的表现,它提供了一种高效的方法来实现键值对的存储和检索。
unordered_map
的用法类似于普通的 map
,但它的键值对没有按照特定的顺序进行排序。因此,在大多数情况下,unordered_map
的查找、插入和删除操作的时间复杂度都是常数时间 O(1),具有非常高的效率。
下面是一些 unordered_map
的基本操作
1.插入元素: 使用 insert()
函数或者下标操作符 []
可以向 unordered_map
中插入新的键值对。如果键已经存在,则对应的值会被更新。
unordered_map<int, string> myMap;
myMap.insert({1, "apple"});
myMap[2] = "banana";
2.访问元素: 使用下标操作符 []
或者 at()
函数可以通过键来访问对应的值。
cout << myMap[1] << endl; // 输出 "apple"
cout << myMap.at(2) << endl; // 输出 "banana"
3.查找元素: 使用 find()
函数可以根据键查找对应的值。如果键存在,则返回指向该键值对的迭代器,否则返回 end()
。
auto it = myMap.find(1);
if (it != myMap.end()) {
cout << "Key found, value is: " << it->second << endl;
} else {
cout << "Key not found!" << endl;
}
4.删除元素: 使用 erase()
函数可以根据键删除对应的键值对。
myMap.erase(1); // 删除键为 1 的键值对
总的来说,unordered_map
是一个非常方便和高效的数据结构,特别适用于需要快速查找键值对的情况。
思路:
我们首先创建了一个
unordered_map<int, int>
类型的哈希表sumAB
,用于存储数组A和B的元素之和以及对应的出现次数。然后,我们使用两层循环遍历数组A和B,将它们的元素之和作为键,在哈希表中对应的值加一。接下来,我们再次使用两层循环遍历数组C和D,计算目标值(即C[i] + D[j] 的相反数)。然后,在哈希表
sumAB
中查找是否存在对应的键,如果存在,则将对应键的值累加到计数器count
上。最后,输出
count
的值,即为满足条件的四元组个数。
代码实现:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int main()
{
int n;
while (cin >> n) // 读取输入的大小 n
{
// 创建四个大小为 n 的动态数组 A、B、C、D
vector<int> A(n), B(n), C(n), D(n);
// 读取输入的四个数组 A、B、C、D
for (int i = 0; i < n; ++i)
{
cin >> A[i] >> B[i] >> C[i] >> D[i];
}
// 计算 A 和 B 数组元素之和的出现次数,并存储到 sumAB 中
unordered_map<int, int> sumAB;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
sumAB[A[i] + B[j]]++; // 计算 A[i] + B[j] 的和,如果和已存在,则增加其出现次数;否则插入新的键值对
}
}
int count = 0;
// 遍历 C 和 D 数组元素,查找与其和为负的 A 和 B 数组元素之和的次数
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
int target = -(C[i] + D[j]); // 计算目标值为 -(C[i] + D[j])
if (sumAB.find(target) != sumAB.end()) // 在 sumAB 中查找目标值,如果找到则累加其出现次数到 count 中
{
count += sumAB[target];
}
}
}
// 输出结果
cout << count << endl;
}
return 0;
}