知识点:
哈希表是根据关键码的值而直接进行访问的数据结构。
当判断一个元素是否在集合里出现时,就要考虑使用哈希法。
常见的三种哈希结构:数组、set(集合),map(映射)。
set和map的底层实现都是红黑树(一种平衡二叉搜索树)。key的值是有序的,只能增删,不能改动
std::set和std::multiset底层实现都是红黑树,std::unordered_set的底层实现是哈希表。
如果题目限制了数值大小,就可以用数组。如果哈希值少,分散跨度大不适用数组。
set占用空间大,速度比数组慢。因为数值映射到key就需要做hash。
题目:
242. 有效的字母异位词 - 力扣(LeetCode) (leetcode-cn.com)
438. 找到字符串中所有字母异位词 - 力扣(LeetCode) (leetcode-cn.com)
vector<int>pHash(26,0);
//记录p中各字母出现的次数
for(int i = 0; i < p.size(); i++) {
pHash[p[i] - 'a']++;
}
切记:在用哈希表想存储字母出现个数的时候,需要用 p[i] - 'a'。
字母异位词分组 - 字母异位词分组 - 力扣(LeetCode) (leetcode-cn.com)
好多map的用法都不是很会。 估计都不记得了。
349. 两个数组的交集 - 力扣(LeetCode) (leetcode-cn.com)
这道题中有set容器的用法,第一次接触。set只能存不同类型
350. 两个数组的交集 II - 力扣(LeetCode) (leetcode-cn.com)
因为存储多个,不可以用set。这道题是map容器用法。
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
//比较两个字符串的大小
if (nums1.size() > nums2.size()) {
return intersect(nums2, nums1);
}
//将nums1存入容器中
unordered_map<int,int>num_set;
for (int num : nums1) {
num_set[num]++;
}
vector<int>res;
for (int num : nums2) {
//如果容器中该元素不为零,则存入,该容器减0
if(num_set.count(num)) {
res.push_back(num);
num_set[num]--;
//该元素减后为零,删除该元素
if (num_set[num] == 0) {
num_set.erase(num);
}
}
}
return res;
}
错误:1、比较两个字符串大小并交换 ,有return,且是nums2在nums1之前,否则会出错。
2、count返回值是0/1,当map中元素个数不为0的时候,要将该元素删除。否则会判断为两个数组仍然交出该元素。
202. 快乐数 - 力扣(LeetCode) (leetcode-cn.com)
这道题存在元素重复出现进而无限循环的情况,所以用哈希表存储,一旦重复出现就跳出循环。
454. 四数相加 II - 力扣(LeetCode) (leetcode-cn.com)
15. 三数之和 - 力扣(LeetCode) (leetcode-cn.com)
错误:去重逻辑搞不懂。整体解题逻辑也不行。
347. 前 K 个高频元素 - 力扣(LeetCode) (leetcode-cn.com)
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int>m;
vector<int>res;
//map数组记录元素和频率
for (int i : nums) {m[i]++;}
//找出最大的频率
int maxk = 0;
for (auto i : m) {
if (i.second > maxk)
maxk = i.second;
}
//依次找k个
while(k > 0) {
for(auto i : m) {
if (i.second == maxk) {
res.push_back(i.first);
k--;
}
}
maxk--;
}
return res;
}
参考文献:
C++常用语法——unordered_set部分(完善中) - Yu_tiann - 博客园 (cnblogs.com)
C++ map通过key获取value_liaosongmao1的专栏-CSDN博客_c++ map获取value
(5条消息) C++中的iterator->second_Tian的博客-CSDN博客_second
杂七杂八补充:for(要遍历的数据类型 遍历变量 : 遍历对象)
for(int num : nums2)
//从nums2的int型数组中依次将值赋值给num,将num带入for语句代码块中执行。
//等同于
int num;
for(int i=0;i<nums2.length;i++)
{
num=nums2[i];
}
set用法
//unordered_set的初始化 - 使用迭代器构造
unordered_set<int> set3(set1.begin(), set1.end());
//find()函数——查找2,找到返回迭代器,失败返回end()
set1.find(2);
//insert()函数——插入元素
set1.insert(3);
map用法
map_name.count(key,valve)
//用数组方式插入数据
mapPerson[3] = "Jerry";
//map中元素的查找
//find() 函数返回一个迭代器指向键值为 key 的元素,如果没找到就返回指向 map 尾部的迭代器。
if(maplive.find(112) == maplive.end())
unordered_map<key,value> m;
value =m[key];
m.count(key),m.find(key)
参数:该函数接受强制性参数k,该参数指定要在Map容器中搜索的键。
返回值:如果Map中存在具有给定键的值,则此函数返回1,否则返回0。
多种容器定义插入元素总结:
vector<int>res;
res.push_back(i);
vector<vector<int>>res(n, vector<int>(n, 0));
res[i][j] = num;
unordered_set<int>set3(set1.begin(), set1.end());
set3.insert(3);
unordered_map<int, int>map1;
map1[3] = "Jerry";
map的first和second的意思
std::map<std::string, int> m = /* fill it */;
auto it = m.begin();
(*it).first
会得到key,
(*it).second
会得到value。
这等同于it->first
和it->second
。