在C++中,unordered_set和unordered_map是两个非常重要的关联容器,它们为开发者提供了基于哈希表的快速查找和插入操作。对于初学者来说,理解这两个容器的概念和基本特性,以及它们的使用场景,是非常有必要的。以下是对unordered_set和unordered_map的个人理解介绍。
[来个例题](禁着点方案数 - MarsCode)
小U有一个长度为nn的数组,这个数组的元素被定义为“禁着点”。她现在希望你找出有多少对正整数 xx 和 yy,满足 x+y=sx+y=s 且 xx 和 yy 都不在禁着点的数组中。注意,(x,y)(x,y) 和 (y,x)(y,x) 被视为不同的正整数对。
这道题很明显就是枚举,然后查找枚举元素是否在禁用数组里面。遍历数组的话时间复杂会很高,因此可以用哈希表unordered_set来帮助我们储存数组,用其复杂度为O(1)来快速排查是否在数组里面。
int solution(int n, vector<int>& a, int s) {
unordered_set<int> forbidden(a.begin(), a.end());
int count = 0;
for (int x = 1; x <=s/2; ++x) {
int y = s - x;
auto it1=forbidden.find(x);
auto it2=forbidden.find(y);
if ( it1==forbidden.end()&&it2==forbidden.end() ) {
if(x==y)
count++;
else
count+=2;
}
}
return count;
}
unordered_set
unordered_set是一个无序集合,它包含唯一的元素,即集合中的每个元素都是唯一的,没有重复。与set不同,unordered_set不保证元素的排序,但通常提供了更快的插入和查找操作,因为它基于哈希表实现。
在unordered_set中,元素的值同时也是唯一地标识它的键。这意味着,你不能通过值来访问元素,而只能通过键(在这里,键和值是相同的)来访问。由于unordered_set不保证元素的排序,因此它不适合需要元素有序的场景。
unordered_set的基本操作包括插入、查找、删除等。插入操作会向集合中添加一个新元素,如果元素已经存在,则插入操作不会改变集合。查找操作会检查一个元素是否在集合中,如果存在,则返回该元素的迭代器,否则返回集合的尾迭代器。删除操作会从集合中移除一个元素。
常用插入:set.insert(1);
unordered_set还提供了一个重要的成员函数count,它返回集合中某个元素的个数。对于unordered_set来说,这个函数的返回值只能是0或1,因为集合中的元素是唯一的。
unordered_map
unordered_map是一个无序关联数组(或哈希表),它存储键值对,并且每个键都是唯一的。与map不同,unordered_map不保证元素的排序,但通常提供了更快的插入、删除和查找操作。
在unordered_map中,键值用于唯一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。例如,你可以有一个unordered_map<int, string>,其中键是整数,值是字符串。
unordered_map的基本操作与unordered_set类似,包括插入、查找、删除等。插入操作会向映射中添加一个新的键值对,如果键已经存在,则新的值会替换旧的值。查找操作会检查一个键是否在映射中,如果存在,则返回该键对应的值的迭代器,否则返回映射的尾迭代器。删除操作会从映射中移除一个键值对。
常用插入:myMap.insert({2, "two"});
unordered_map还提供了一个重要的成员函数operator[],它允许使用键作为参数直接访问对应的值。这个操作符在键不存在时会插入一个新的键值对,其中值为默认构造的值。因此,在使用这个操作符时需要小心,以避免不必要的插入操作。
使用场景
unordered_set适用于只关心元素是否存在的场景,不需要存储任何附加数据。例如,你可以使用unordered_set来检查一个元素是否已经被添加到集合中。unordered_map适用于需要通过键来查找值的场景,常用于键值对的映射存储,如字典。例如,你可以使用unordered_map来存储学生的学号和姓名,以便通过学号快速查找学生的姓名。
查找是否存在元素
哈希表最重要的一个点就是可以快速查找是否存在查找元素,因此我们可以用find来快速寻找。
auto it=set.find(x)
这里it是一个迭代器,指代查找元素的,如果没有查找的元素,那么就是it==set.end();
如果用的是unordered_map,那么it->first便代表查找元素,也就是键,而it->second则代表以查找元素为键的值。
总的来说,unordered_set和unordered_map是C++中非常有用的两个关联容器,它们提供了基于哈希表的快速查找和插入操作。理解这两个容器的概念和基本特性是非常重要的.