unordered_map< k , v > 无序映射
内部实现: 哈希表(Hash Table)
特点
- 无序
- 高效查找:通过哈希函数直接将值映射到特定位置,增删查时间复杂度O(1)
- k唯一:每个键只能对应一个值
常用操作
find(key):查找键key,返回一个迭代器 。如果找到,迭代器指向该键值对;如果没找到,指向end()。
例如:
cpp
unordered_map<int, int> hashtable;
auto it = hashtable.find(nums);
//如果没找到:
it == hashtable.end()
//否则
it->first指向键值对中的键
it->second指向键值对中的值
insert({key, value})或hashtable[key] = value:插入键值对。erase(key):删除键为key的键值对。size():返回键值对的数量。empty():判断是否为空。
unordered_set< k >无序集合
内部实现也是哈希表
特点
- 唯一性 :
unordered_set中的元素是唯一的,不允许重复。- 无序性 :元素没有固定的顺序。元素的存储位置由其哈希值决定。
- 基于哈希表 :
unordered_set内部通常使用哈希表实现。这使得它的插入、删除和查找操作在平均情况下 具有常数时间复杂度 O(1)。
常用操作
- insert(k):插入
- erase(k):删除值为k的元素
- find():查找元素
- clear():清除元素
- count():统计容器中某个指定元素的出现次数,只会返回1或0
1. 两数之和
要找数值 ,返回**下标,**一个键值对用unordered_map
键 :数值,值:该数所在的下标
利用find寻找和数(比遍历快)
先找再插入,防止自己加自己
cpp
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hashtable;//存放 数值:下标
for (int i = 0; i < nums.size(); ++i)
{
auto it = hashtable.find(target - nums[i]);
if (it != hashtable.end())
{//如果找到,就返回
return {it->second, i};
}
hashtable[nums[i]] = i;//没有找到,把当前值和下标存入
}
return {};
}
};
49. 字母异位词分组
要找同字母的单词,返回这些单词,也是键值对unordered_map
键:排序后的字母,值:这些字母的单词
这样插入,同字母的单词都在一个键对应着
cpp
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string,vector<string>> mp;
vector<vector<string>> ans;
//排序之和存入map中
for(auto s:strs)
{
string k = s;
sort(k.begin(),k.end());
mp[k].emplace_back(s);
}
for(auto it = mp.begin();it!=mp.end();it++)
{
ans.emplace_back(it->second);
}
return ans;
}
};
128. 最长连续序列
一个vector中可能有多个一样的值,为了避免重复统计这些,可以用unordered_set
这个代码很关键的一步,判断元素是否是连续序列的第一个,即比它小1的元素不存在:if(s.find(it-1)==s.end())//当前元素是序列的第一个元素(这一步用count来写更清楚一些)
尽管代码看起来是嵌套循环,但由于 while 循环受到 if 条件的严格限制,使得每个元素在 while 循环中最多被访问一次,如果if判断不成功,这个循环也就continue了。因此,整个算法的时间复杂度仍然是线性的,即 O(N)。
cpp
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
if(nums.empty())
{
return 0;
}
int n = nums.size();
unordered_set<int> s;
//将元素插入s,使每一个元素只出现一次
for(int num:nums)
{
s.insert(num);
}
int ans = 0;
int curnum;
int curlong = 0;
for(auto & it: s)
{
if(s.find(it-1)==s.end())//当前元素是序列的第一个元素
{
curnum = it;
while(s.find(curnum)!=s.end())
{
curlong++;
curnum++;
}
ans = max(ans,curlong);
curlong = 0;
}
}
ans = max(ans,curlong);
return ans;
}
};