5)set和map容器、哈希表总结

什么是set和map

学过数据结构的直接跳过。

set在C++中称为集合,里面存放了一系列数据(这些数据一般是不重复的)。

这和vector有啥区别?区别就是,我们可以在O(1)时间复杂度内就能知道这个数据内包不包含某个值。怎么实现的你别管,你只需要知道有这么个功能就行。

而map在set的基础上更近一步,可以以set里面的值作为下标来存放数据,这样的话通过想要的下标来访问数据就可以在O(1)时间复杂度内完成。

这么说起来可能有点抽象,那我就用最简单说法:这个数组的下标不再是冷冰冰的01234,而是想定义成啥样就定义成啥样。比如说我想记录动物园里面的小动物,有3只鸟,5只猪,13只狗就可以写成:

animal["bird"] = 3;
animal["pig"] = 5;
animal["dog"] = 13;

C++内置的set和map

在C++里有多种set和多种map,分别叫:

set、map、multiset、multimap、unordered_set、unordered_map、unordered_multiset、unordered_multimap等等,但这些不重要,重要的是你只需要使用unordered_set和unordered_map就行了。

unordered代表无序,传进去的set和map不会多一个排序步骤,所以效率更高。

当然,使用set和map也能完成题目,单词还更好记,只不过效率上会差一点。

#include <unordered_set>
#include <unordered_map>

set的使用方法例:

创建一个新set:

unordered_set<int> st;

创建一个新set并初始就填入一定的数据:

// 因为是不重复的,所以虽然数组里有两个5,但实际上st里只会放一个
unordered_set<int> st{1, 3, 5, 5, 2};

插入数据:

st.insert(7);

删除数据:

st.erase(5);

寻找set里是否存在某一个数据:

unordered_set<int>::iterator iter = st.find(3);

find函数返回的是一个迭代器,如果找到了该数据就返回该数据的迭代器,如果找不到该数据就返回end()迭代器。

当然一般而言我们不会再专门用一个迭代器去接收.find(),常用的使用方法是这样的:

if (st.find(3) != st.end()) {
    // 返回的不是end(),说明找到了该数据
}
else {
    // 返回的是end(),说明找不到该数据
}

既然有迭代器,那自然也就有遍历了

for (auto iter = st.begin(); iter != st.end(); iter++) {
    cout << *iter;
}

 不用迭代器遍历也是可以的

for (int num : st) {
    cout << num;
}

map的使用方法例

map和set的使用方法很像。顺带一提,map底层数据的存储模式和pair<>一样。需要输入两个数据类型,第一个是key的类型,第二个是value的类型

unordered_map<string, int> animal; // 创建
animal.insert({"cat", 3}); // 插入
animal.erase("cat"); // 删除
if (animal.find("cat") != animal.end()) { // 寻找特定值

}
else {
    
}

因为存储模式和pair<>一样,所以遍历的时候接收的值就是pair<>

for (auto iter = animal.begin(); iter != animal.end(); iter++) {
    cout << (*iter).first;
    cout << (*iter).second;
}

不过迭代器看着很麻烦,建议用另一种遍历方法

for (auto pr : animal) {
    cout << pr.first;
    cout << pr.second;
}

相较于set,map还有一些额外用法

map可以像使用数组一样,将key值当数组下标来访问值。

cout << animal["cat"];

当你需要给map里添加内容的时候,并不一定需要用insert,直接使用中括号就可以了。

animal["dog"] = 3; // 此时map中没有dog,会自动新建一个dog来存储3
animal["dog"] = 4; // 此时map中已经有dog了,会将3变成4

如果value的值是int型,那么当我们在计数的时候甚至可以直接使用++。如果key值不存在会直接创建一个key值进入map中。

animal["mouse"]++; // 此时map中没有mouse,会自动创建一个mouse,value为0,++之后就变成1了

哈希表题目总结

像有些题目属于一眼哈希,多思考一秒钟都是对哈希表的不尊重的:

349. 两个数组的交集 - 力扣(LeetCode)

242. 有效的字母异位词 - 力扣(LeetCode)

除了这种一眼哈希的题目之外,还有遇到如下情况可以使用哈希表:

当需要找到一个数组中两数之和等于某特定数的时候。

1. 两数之和 - 力扣(LeetCode)

另外,先前说了,在一些前缀和的问题之中也可以使用哈希表。

比如说题目是找到一串数组是否存在一串子序列,使子序列之和等于某特定值的时候,就可以转换为找到某两个前缀,使它们之差等于某特定值,和上面的两数之和那道题就非常像了。

560. 和为 K 的子数组 - 力扣(LeetCode)

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值